From 9dba5034afbd070bc6efea230a9938cf50244ba0 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 24 Jan 2024 17:26:00 +0800 Subject: [PATCH 1/8] Use vue instead of plain template to render suscribe div of issue --- routers/web/repo/issue_watch.go | 4 +- .../repo/issue/view_content/sidebar.tmpl | 24 ++---- web_src/js/components/issue/Subscribe.vue | 76 +++++++++++++++++++ web_src/js/index.js | 3 + web_src/js/init.js | 26 +++++++ web_src/js/svg.js | 4 + 6 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 web_src/js/components/issue/Subscribe.vue create mode 100644 web_src/js/init.js diff --git a/routers/web/repo/issue_watch.go b/routers/web/repo/issue_watch.go index 1cb5cc7162d89..fc04c4e40b3cd 100644 --- a/routers/web/repo/issue_watch.go +++ b/routers/web/repo/issue_watch.go @@ -41,7 +41,7 @@ func IssueWatch(ctx *context.Context) { return } - watch, err := strconv.ParseBool(ctx.Req.PostForm.Get("watch")) + watch, err := strconv.ParseBool(ctx.FormString("watch")) if err != nil { ctx.ServerError("watch is not bool", err) return @@ -52,5 +52,5 @@ func IssueWatch(ctx *context.Context) { return } - ctx.Redirect(issue.Link()) + ctx.JSONOK() } diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index 4334e4bcbdc21..f46cc0d630e58 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -267,23 +267,13 @@ {{if and $.IssueWatch (not .Repository.IsArchived)}}
-
- {{ctx.Locale.Tr "notification.notifications"}} -
-
- - {{$.CsrfTokenHtml}} - -
-
+
{{end}} {{if .Repository.IsTimetrackerEnabled $.Context}} diff --git a/web_src/js/components/issue/Subscribe.vue b/web_src/js/components/issue/Subscribe.vue new file mode 100644 index 0000000000000..5193ffe044086 --- /dev/null +++ b/web_src/js/components/issue/Subscribe.vue @@ -0,0 +1,76 @@ + + diff --git a/web_src/js/index.js b/web_src/js/index.js index 4713618506b0c..227950038245d 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -85,6 +85,7 @@ import {initRepoIssueList} from './features/repo-issue-list.js'; import {initCommonIssueListQuickGoto} from './features/common-issue-list.js'; import {initRepoDiffCommitBranchesAndTags} from './features/repo-diff-commit.js'; import {initDirAuto} from './modules/dirauto.js'; +import {initIssueSubsribe} from './components/issue/Subscribe.vue'; // Init Gitea's Fomantic settings initGiteaFomantic(); @@ -184,4 +185,6 @@ onDomReady(() => { initRepoDiffView(); initPdfViewer(); initScopedAccessTokenCategories(); + + initIssueSubsribe(); }); diff --git a/web_src/js/init.js b/web_src/js/init.js new file mode 100644 index 0000000000000..eadba36fc8c78 --- /dev/null +++ b/web_src/js/init.js @@ -0,0 +1,26 @@ +import {createApp} from 'vue'; + +function convertName(o) { + return o.replace(/-(\w)/g, (_, c) => { + return c ? c.toUpperCase() : ''; + }); +} + +export function initComponent(id, sfc) { + const el = document.getElementById(id); + if (!el) return; + + const data = {}; + + el.getAttributeNames().forEach((attr) => { + if (attr.startsWith('data-locale-')) { + data.locale = data.locale || {}; + data.locale[convertName(attr.slice(12))] = el.getAttribute(attr); + } else if (attr.startsWith('data-')) { + data[convertName(attr.slice(5))] = el.getAttribute(attr); + } + }); + + const view = createApp(sfc, data); + view.mount(el); +} diff --git a/web_src/js/svg.js b/web_src/js/svg.js index c2a96fba3f040..048b8362d885e 100644 --- a/web_src/js/svg.js +++ b/web_src/js/svg.js @@ -69,6 +69,8 @@ import octiconTag from '../../public/assets/img/svg/octicon-tag.svg'; import octiconTriangleDown from '../../public/assets/img/svg/octicon-triangle-down.svg'; import octiconX from '../../public/assets/img/svg/octicon-x.svg'; import octiconXCircleFill from '../../public/assets/img/svg/octicon-x-circle-fill.svg'; +import octiconMute from '../../public/assets/img/svg/octicon-mute.svg'; +import octiconUnmute from '../../public/assets/img/svg/octicon-unmute.svg'; const svgs = { 'gitea-double-chevron-left': giteaDoubleChevronLeft, @@ -140,6 +142,8 @@ const svgs = { 'octicon-triangle-down': octiconTriangleDown, 'octicon-x': octiconX, 'octicon-x-circle-fill': octiconXCircleFill, + 'octicon-mute': octiconMute, + 'octicon-unmute': octiconUnmute, }; // TODO: use a more general approach to access SVG icons. From 645b5db8210a012f2a2be21233adf86a8ca3d88d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 24 Jan 2024 17:34:52 +0800 Subject: [PATCH 2/8] Add some comment --- web_src/js/components/issue/Subscribe.vue | 2 +- web_src/js/init.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/web_src/js/components/issue/Subscribe.vue b/web_src/js/components/issue/Subscribe.vue index 5193ffe044086..9a879931e0b7b 100644 --- a/web_src/js/components/issue/Subscribe.vue +++ b/web_src/js/components/issue/Subscribe.vue @@ -3,7 +3,7 @@ import {initComponent} from '../../init.js'; import {SvgIcon} from '../../svg.js'; import {POST} from '../../modules/fetch.js'; import {showErrorToast} from '../../modules/toast.js'; -import { ref } from 'vue'; +import {ref} from 'vue'; const sfc = { name: 'IssueSubscribe', diff --git a/web_src/js/init.js b/web_src/js/init.js index eadba36fc8c78..714db45441903 100644 --- a/web_src/js/init.js +++ b/web_src/js/init.js @@ -1,11 +1,15 @@ import {createApp} from 'vue'; +// convertName convert the html tag a-b to aB function convertName(o) { return o.replace(/-(\w)/g, (_, c) => { return c ? c.toUpperCase() : ''; }); } +// initComponent will mount the component with tag id named id and vue sfc +// it will also assign all attributes of the tag with the prefix data-locale- and data- +// to the component as props export function initComponent(id, sfc) { const el = document.getElementById(id); if (!el) return; From 8bcffb666044987cfc74f0ba28f5d725623a8df7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 24 Jan 2024 18:11:08 +0800 Subject: [PATCH 3/8] Fix frontend lint --- web_src/js/init.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web_src/js/init.js b/web_src/js/init.js index 714db45441903..7a8298821d5dc 100644 --- a/web_src/js/init.js +++ b/web_src/js/init.js @@ -16,14 +16,14 @@ export function initComponent(id, sfc) { const data = {}; - el.getAttributeNames().forEach((attr) => { + for (const attr of el.getAttributeNames()) { if (attr.startsWith('data-locale-')) { data.locale = data.locale || {}; data.locale[convertName(attr.slice(12))] = el.getAttribute(attr); } else if (attr.startsWith('data-')) { data[convertName(attr.slice(5))] = el.getAttribute(attr); } - }); + } const view = createApp(sfc, data); view.mount(el); From 95eabd507b2cf2b4e8aa3bd7a1cb28629b551f09 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 24 Jan 2024 18:16:32 +0800 Subject: [PATCH 4/8] Add test for the js function --- web_src/js/init.js | 2 +- web_src/js/init.test.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 web_src/js/init.test.js diff --git a/web_src/js/init.js b/web_src/js/init.js index 7a8298821d5dc..69f634e90fd1b 100644 --- a/web_src/js/init.js +++ b/web_src/js/init.js @@ -1,7 +1,7 @@ import {createApp} from 'vue'; // convertName convert the html tag a-b to aB -function convertName(o) { +export function convertName(o) { return o.replace(/-(\w)/g, (_, c) => { return c ? c.toUpperCase() : ''; }); diff --git a/web_src/js/init.test.js b/web_src/js/init.test.js new file mode 100644 index 0000000000000..356b63bb694e5 --- /dev/null +++ b/web_src/js/init.test.js @@ -0,0 +1,7 @@ +import {convertName} from './init.js'; + +test('init', () => { + expect(convertName('abc')).toEqual('abc'); + expect(convertName('abc-repo')).toEqual('abcRepo'); + expect(convertName('abc-repo-issue')).toEqual('abcRepoIssue'); +}); From b3385ba3bbd94a443c985c6871acac362aaf13df Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 24 Jan 2024 18:26:17 +0800 Subject: [PATCH 5/8] make initComponent simpler --- web_src/js/components/issue/Subscribe.vue | 5 ----- web_src/js/init.js | 7 +++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/web_src/js/components/issue/Subscribe.vue b/web_src/js/components/issue/Subscribe.vue index 9a879931e0b7b..efa6a9a767a62 100644 --- a/web_src/js/components/issue/Subscribe.vue +++ b/web_src/js/components/issue/Subscribe.vue @@ -16,16 +16,11 @@ const sfc = { watchLink: { type: String, default: false, - }, - locale: { - type: Object, - default: () => {}, } }, data() { return { isLoading: false, - isWatching: false, }; }, setup(props) { diff --git a/web_src/js/init.js b/web_src/js/init.js index 69f634e90fd1b..c70d9ea602104 100644 --- a/web_src/js/init.js +++ b/web_src/js/init.js @@ -25,6 +25,13 @@ export function initComponent(id, sfc) { } } + if (!sfc.props.locale) { + sfc.props.locale = { + type: Object, + default: () => {}, + }; + } + const view = createApp(sfc, data); view.mount(el); } From d10424fbcee8142c0e3ecdd15050edebe0a5b6ef Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 24 Jan 2024 18:31:46 +0800 Subject: [PATCH 6/8] make props more strict --- web_src/js/components/issue/Subscribe.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/components/issue/Subscribe.vue b/web_src/js/components/issue/Subscribe.vue index efa6a9a767a62..6b6023bd38262 100644 --- a/web_src/js/components/issue/Subscribe.vue +++ b/web_src/js/components/issue/Subscribe.vue @@ -15,7 +15,7 @@ const sfc = { }, watchLink: { type: String, - default: false, + required: true, } }, data() { From 97b14dd6eb3aa25b5086016356c4bad8683dbe7e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 24 Jan 2024 19:33:27 +0800 Subject: [PATCH 7/8] remove trace content --- web_src/js/components/issue/Subscribe.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/web_src/js/components/issue/Subscribe.vue b/web_src/js/components/issue/Subscribe.vue index 6b6023bd38262..7048f70e24ea2 100644 --- a/web_src/js/components/issue/Subscribe.vue +++ b/web_src/js/components/issue/Subscribe.vue @@ -36,7 +36,6 @@ const sfc = { this.isLoading = true; try { const resp = await POST(`${this.watchLink}?watch=${!this.isWatching}`); - console.info(resp.status, resp.status === 200); if (resp.status !== 200) { showErrorToast(`Update watching status return: ${resp.status}`); return; From 1930051a971545577c9e0305c5e965bfd0c114f8 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 27 Jan 2024 20:57:30 +0800 Subject: [PATCH 8/8] add loading --- web_src/js/components/issue/Subscribe.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/components/issue/Subscribe.vue b/web_src/js/components/issue/Subscribe.vue index 7048f70e24ea2..75b2a05b6585f 100644 --- a/web_src/js/components/issue/Subscribe.vue +++ b/web_src/js/components/issue/Subscribe.vue @@ -60,7 +60,7 @@ export function initIssueSubsribe() {