From 09941efaf8ea97fdddd886bc3336e000cca627cb Mon Sep 17 00:00:00 2001 From: Jonathan Tran Date: Fri, 2 Jun 2023 18:50:15 -0400 Subject: [PATCH 1/8] Change API token UI to use selects --- options/locale/locale_en-US.ini | 3 + templates/user/settings/applications.tmpl | 21 +- .../components/ScopedAccessTokenSelector.vue | 181 +++++++----------- 3 files changed, 86 insertions(+), 119 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 195252c47d17..1263063933fc 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -810,6 +810,9 @@ repo_and_org_access = Repository and Organization Access permissions_public_only = Public only permissions_access_all = All (public, private, and limited) select_permissions = Select permissions +permission_no_access = No Access +permission_read = Read +permission_write = Write scoped_token_desc = Selected token scopes limit authentication only to the corresponding API routes. Read the documentation for more information. at_least_one_permission = You must select at least one permission to create a token permissions_list = Permissions: diff --git a/templates/user/settings/applications.tmpl b/templates/user/settings/applications.tmpl index 2b7db82dae6e..d494b53f8486 100644 --- a/templates/user/settings/applications.tmpl +++ b/templates/user/settings/applications.tmpl @@ -69,20 +69,17 @@ {{.locale.Tr "settings.select_permissions"}} -
+

{{$.locale.Tr "settings.scoped_token_desc" (printf `href="/api/swagger" target="_blank"`) (printf `href="https://docs.gitea.com/development/oauth2-provider#scopes" target="_blank"`) | Str2html}} +

+
+
- - {{if .IsAdmin}} - - {{end}} - - - - - - -
{{.locale.Tr "settings.at_least_one_permission"}} diff --git a/web_src/js/components/ScopedAccessTokenSelector.vue b/web_src/js/components/ScopedAccessTokenSelector.vue index 769f3262b441..2298d05161d8 100644 --- a/web_src/js/components/ScopedAccessTokenSelector.vue +++ b/web_src/js/components/ScopedAccessTokenSelector.vue @@ -1,51 +1,24 @@ @@ -55,43 +28,65 @@ import {showElem} from '../utils/dom.js'; const sfc = { props: { - category: { + isAdmin: { + type: Boolean, + required: true, + }, + noAccessLabel: { + type: String, + required: true, + }, + readLabel: { + type: String, + required: true, + }, + writeLabel: { type: String, required: true, }, }, - data: () => ({ - categorySelected: false, - disableIndividual: false, - readSelected: false, - writeSelected: false, - }), + computed: { + categories() { + const categories = [ + 'activitypub', + ]; + if (this.isAdmin) { + categories.push('admin'); + } + categories.push( + 'issue', + 'misc', + 'notification', + 'organization', + 'package', + 'repository', + 'user'); + return categories; + } + }, - methods: { - /** - * When entire category is toggled - * @param {Event} e - */ - onCategoryInput(e) { - e.preventDefault(); - this.disableIndividual = this.$refs.category.checked; - this.writeSelected = this.$refs.category.checked; - this.readSelected = this.$refs.category.checked; - }, + mounted() { + document.getElementById('scoped-access-submit').addEventListener('click', this.onClickSubmit); + }, - /** - * When an individual level of category is toggled - * @param {Event} e - */ - onIndividualInput(e) { + unmounted() { + document.getElementById('scoped-access-submit').removeEventListener('click', this.onClickSubmit); + }, + + methods: { + onClickSubmit(e) { e.preventDefault(); - if (this.$refs.write.checked) { - this.readSelected = true; + // check that at least one scope has been selected + for (const el of document.getElementsByClassName('scoped-access-token-input')) { + if (el.value) { + document.getElementById('scoped-access-form').submit(); + } } - this.categorySelected = this.$refs.write.checked; - }, - } + // no scopes selected, show validation error + showElem(document.getElementById('scoped-access-warning')); + } + }, }; export default sfc; @@ -100,39 +95,11 @@ export default sfc; * Initialize category toggle sections */ export function initScopedAccessTokenCategories() { - for (const el of document.getElementsByTagName('scoped-access-token-category')) { - const category = el.getAttribute('category'); - createApp(sfc, { - category, - }).mount(el); + for (const el of document.getElementsByClassName('scoped-access-token-mount')) { + createApp({}) + .component('scoped-access-token-selector', sfc) + .mount(el); } - - document.getElementById('scoped-access-submit')?.addEventListener('click', (e) => { - e.preventDefault(); - // check that at least one scope has been selected - for (const el of document.getElementsByClassName('scoped-access-token-input')) { - if (el.checked) { - document.getElementById('scoped-access-form').submit(); - } - } - // no scopes selected, show validation error - showElem(document.getElementById('scoped-access-warning')); - }); } - - From 62a0b887e7746ec89fca4d2d5ccb2d1e60472b65 Mon Sep 17 00:00:00 2001 From: Jonathan Tran Date: Tue, 6 Jun 2023 14:29:02 -0400 Subject: [PATCH 2/8] Fix to hide the warning message on second attempt --- web_src/js/components/ScopedAccessTokenSelector.vue | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/web_src/js/components/ScopedAccessTokenSelector.vue b/web_src/js/components/ScopedAccessTokenSelector.vue index 2298d05161d8..4c1d4eca74dc 100644 --- a/web_src/js/components/ScopedAccessTokenSelector.vue +++ b/web_src/js/components/ScopedAccessTokenSelector.vue @@ -24,7 +24,7 @@ + + From e47ae63555ed2ebb4227db30f6dc8cbee5f2384f Mon Sep 17 00:00:00 2001 From: Jonathan Tran Date: Thu, 8 Jun 2023 10:36:53 -0400 Subject: [PATCH 6/8] Change to use existing SVG with rotation --- web_src/css/base.css | 1 - web_src/js/components/ScopedAccessTokenSelector.vue | 8 +++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/web_src/css/base.css b/web_src/css/base.css index 06bdfa333a61..a35eccb26bea 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -13,7 +13,6 @@ --checkbox-mask-checked: url('data:image/svg+xml;utf8,'); --checkbox-mask-indeterminate: url('data:image/svg+xml;utf8,'); --octicon-chevron-right: url('data:image/svg+xml;utf8,'); - --octicon-chevron-down: url('data:image/svg+xml;utf8,'); /* non-color variables */ --border-radius: 0.28571429rem; --opacity-disabled: 0.55; diff --git a/web_src/js/components/ScopedAccessTokenSelector.vue b/web_src/js/components/ScopedAccessTokenSelector.vue index e029d2e392dc..9a9db34ebebb 100644 --- a/web_src/js/components/ScopedAccessTokenSelector.vue +++ b/web_src/js/components/ScopedAccessTokenSelector.vue @@ -117,7 +117,7 @@ export function initScopedAccessTokenCategories() { position: relative; } -/* ::before and ::after pseudo elements doesn't work on select elements, so we +/* ::before and ::after pseudo elements don't work on select elements, so we need to put it on the parent. */ .access-token-select-wrapper::before { position: absolute; @@ -130,8 +130,10 @@ need to put it on the parent. */ height: 14px; mask-size: cover; -webkit-mask-size: cover; - mask-image: var(--octicon-chevron-down); - -webkit-mask-image: var(--octicon-chevron-down); + mask-image: var(--octicon-chevron-right); + -webkit-mask-image: var(--octicon-chevron-right); + /* Point the chevron down. */ + transform: rotate(90deg); background: currentcolor; border: 1px solid var(--color-body); /* workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1671784 */ } From 93e3ad1980f5ca95cb71c1cb890f978fbd4ffb22 Mon Sep 17 00:00:00 2001 From: Jonathan Tran Date: Thu, 8 Jun 2023 10:53:24 -0400 Subject: [PATCH 7/8] Remove unneeded workaround --- web_src/js/components/ScopedAccessTokenSelector.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/web_src/js/components/ScopedAccessTokenSelector.vue b/web_src/js/components/ScopedAccessTokenSelector.vue index 9a9db34ebebb..4dcf0a5e5ec2 100644 --- a/web_src/js/components/ScopedAccessTokenSelector.vue +++ b/web_src/js/components/ScopedAccessTokenSelector.vue @@ -135,7 +135,6 @@ need to put it on the parent. */ /* Point the chevron down. */ transform: rotate(90deg); background: currentcolor; - border: 1px solid var(--color-body); /* workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1671784 */ } .ui.form .access-token-select { From 896969098140d66447bab9b20d4c59f299be6bf6 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 12 Jun 2023 18:50:37 +0200 Subject: [PATCH 8/8] move select styling to gitea-select class --- web_src/css/index.css | 1 + web_src/css/modules/select.css | 25 ++++++++++++++ .../components/ScopedAccessTokenSelector.vue | 34 +------------------ 3 files changed, 27 insertions(+), 33 deletions(-) create mode 100644 web_src/css/modules/select.css diff --git a/web_src/css/index.css b/web_src/css/index.css index 689c3f4a2970..c9cc1d8032bb 100644 --- a/web_src/css/index.css +++ b/web_src/css/index.css @@ -1,6 +1,7 @@ @import "./modules/normalize.css"; @import "./modules/animations.css"; @import "./modules/button.css"; +@import "./modules/select.css"; @import "./modules/tippy.css"; @import "./modules/modal.css"; @import "./modules/breadcrumb.css"; diff --git a/web_src/css/modules/select.css b/web_src/css/modules/select.css new file mode 100644 index 000000000000..57a87888e029 --- /dev/null +++ b/web_src/css/modules/select.css @@ -0,0 +1,25 @@ +.gitea-select { + position: relative; +} + +.gitea-select select { + appearance: none; /* hide default triangle */ +} + +/* ::before and ::after pseudo elements don't work on select elements, + so we need to put it on the parent. */ +.gitea-select::after { + position: absolute; + top: 12px; + right: 8px; + pointer-events: none; + content: ''; + width: 14px; + height: 14px; + mask-size: cover; + -webkit-mask-size: cover; + mask-image: var(--octicon-chevron-right); + -webkit-mask-image: var(--octicon-chevron-right); + transform: rotate(90deg); /* point the chevron down */ + background: currentcolor; +} diff --git a/web_src/js/components/ScopedAccessTokenSelector.vue b/web_src/js/components/ScopedAccessTokenSelector.vue index 4dcf0a5e5ec2..b4b9b979eadd 100644 --- a/web_src/js/components/ScopedAccessTokenSelector.vue +++ b/web_src/js/components/ScopedAccessTokenSelector.vue @@ -3,7 +3,7 @@ -
+