From 3de9e63fd04d61e08fcbdec035c9f138347d9f37 Mon Sep 17 00:00:00 2001
From: Zettat123 <zettat123@gmail.com>
Date: Sat, 11 Mar 2023 00:42:38 +0800
Subject: [PATCH] Hide target selector if tag exists when creating new release
 (#23171)

Close #22649.

|status|screenshot|
|-|-|
|empty tag name|<img
src="https://user-images.githubusercontent.com/15528715/221490165-fd3abd2e-6dc5-4562-bece-d1d6a305479e.png"
width="300px"/>|
|new tag|<img
src="https://user-images.githubusercontent.com/15528715/221490450-49b2a48e-b206-49f4-bd79-34b1ea64156f.png"
width="300px"/>|
|existing tag|<img
src="https://user-images.githubusercontent.com/15528715/221490301-4d1879dd-4947-4abc-9b9a-e77be1806981.png"
width="300px"/>|
---
 options/locale/locale_en-US.ini     |  2 ++
 templates/repo/release/new.tmpl     | 33 +++++++++++++-----------
 web_src/js/features/repo-release.js | 39 +++++++++++++++++++++++++++--
 web_src/js/index.js                 |  4 +--
 4 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 095257b365..dccf184335 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -2290,6 +2290,8 @@ release.edit_subheader = Releases organize project versions.
 release.tag_name = Tag name
 release.target = Target
 release.tag_helper = Choose an existing tag or create a new tag.
+release.tag_helper_new = New tag. This tag will be created from the target.
+release.tag_helper_existing = Existing tag.
 release.title = Title
 release.content = Content
 release.prerelease_desc = Mark as Pre-Release
diff --git a/templates/repo/release/new.tmpl b/templates/repo/release/new.tmpl
index 37d7ca0321..d7c580fed9 100644
--- a/templates/repo/release/new.tmpl
+++ b/templates/repo/release/new.tmpl
@@ -20,22 +20,27 @@
 						<b>{{.tag_name}}</b><span class="at">@</span><strong>{{.tag_target}}</strong>
 					{{else}}
 						<input id="tag-name" name="tag_name" value="{{.tag_name}}" placeholder="{{.locale.Tr "repo.release.tag_name"}}" autofocus required maxlength="255">
-						<span class="at">@</span>
-						<div class="ui selection dropdown">
-							<input type="hidden" name="tag_target" value="{{.tag_target}}"/>
-							{{svg "octicon-git-branch"}}
-							<div class="text">
-								{{.locale.Tr "repo.release.target"}} :
-								<strong id="repo-branch-current">{{.Repository.DefaultBranch}}</strong>
-							</div>
-							{{svg "octicon-triangle-down" 14 "dropdown icon"}}
-							<div class="menu">
-								{{range .Branches}}
-									<div class="item" data-value="{{.}}">{{.}}</div>
-								{{end}}
+						<input id="tag-name-editor" type="hidden" data-existing-tags={{Json .Tags}} data-tag-helper={{.locale.Tr "repo.release.tag_helper"}} data-tag-helper-new={{.locale.Tr "repo.release.tag_helper_new"}} data-tag-helper-existing={{.locale.Tr "repo.release.tag_helper_existing"}} />
+						<div id="tag-target-selector" class="gt-dib">
+							<span class="at">@</span>
+							<div class="ui selection dropdown">
+								<input type="hidden" name="tag_target" value="{{.tag_target}}"/>
+								{{svg "octicon-git-branch"}}
+								<div class="text">
+									{{.locale.Tr "repo.release.target"}} :
+									<strong id="repo-branch-current">{{.Repository.DefaultBranch}}</strong>
+								</div>
+								{{svg "octicon-triangle-down" 14 "dropdown icon"}}
+								<div class="menu">
+									{{range .Branches}}
+										<div class="item" data-value="{{.}}">{{.}}</div>
+									{{end}}
+								</div>
 							</div>
 						</div>
-						<span class="help">{{.locale.Tr "repo.release.tag_helper"}}</span>
+						<div>
+							<span id="tag-helper" class="help gt-mt-2">{{.locale.Tr "repo.release.tag_helper"}}</span>
+						</div>
 					{{end}}
 				</div>
 			</div>
diff --git a/web_src/js/features/repo-release.js b/web_src/js/features/repo-release.js
index a061c6b23f..a230d7765e 100644
--- a/web_src/js/features/repo-release.js
+++ b/web_src/js/features/repo-release.js
@@ -3,7 +3,7 @@ import {attachTribute} from './tribute.js';
 import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js';
 import {initEasyMDEImagePaste} from './comp/ImagePaste.js';
 import {createCommentEasyMDE} from './comp/EasyMDE.js';
-import {hideElem} from '../utils/dom.js';
+import {hideElem, showElem} from '../utils/dom.js';
 
 export function initRepoRelease() {
   $(document).on('click', '.remove-rel-attach', function() {
@@ -14,8 +14,43 @@ export function initRepoRelease() {
   });
 }
 
+export function initRepoReleaseNew() {
+  const $repoReleaseNew = $('.repository.new.release');
+  if (!$repoReleaseNew.length) return;
 
-export function initRepoReleaseEditor() {
+  initTagNameEditor();
+  initRepoReleaseEditor();
+}
+
+function initTagNameEditor() {
+  const el = document.getElementById('tag-name-editor');
+  if (!el) return;
+
+  const existingTags = JSON.parse(el.getAttribute('data-existing-tags'));
+  if (!Array.isArray(existingTags)) return;
+
+  const defaultTagHelperText = el.getAttribute('data-tag-helper');
+  const newTagHelperText = el.getAttribute('data-tag-helper-new');
+  const existingTagHelperText = el.getAttribute('data-tag-helper-existing');
+
+  document.getElementById('tag-name').addEventListener('keyup', (e) => {
+    const value = e.target.value;
+    if (existingTags.includes(value)) {
+      // If the tag already exists, hide the target branch selector.
+      hideElem('#tag-target-selector');
+      document.getElementById('tag-helper').innerText = existingTagHelperText;
+    } else {
+      showElem('#tag-target-selector');
+      if (value) {
+        document.getElementById('tag-helper').innerText = newTagHelperText;
+      } else {
+        document.getElementById('tag-helper').innerText = defaultTagHelperText;
+      }
+    }
+  });
+}
+
+function initRepoReleaseEditor() {
   const $editor = $('.repository.new.release .content-editor');
   if ($editor.length === 0) {
     return;
diff --git a/web_src/js/index.js b/web_src/js/index.js
index 611c09d2b8..6b4f4ef3eb 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -76,7 +76,7 @@ import {
 import {initViewedCheckboxListenerFor} from './features/pull-view-file.js';
 import {initOrgTeamSearchRepoBox, initOrgTeamSettings} from './features/org-team.js';
 import {initUserAuthWebAuthn, initUserAuthWebAuthnRegister} from './features/user-auth-webauthn.js';
-import {initRepoRelease, initRepoReleaseEditor} from './features/repo-release.js';
+import {initRepoRelease, initRepoReleaseNew} from './features/repo-release.js';
 import {initRepoEditor} from './features/repo-editor.js';
 import {initCompSearchUserBox} from './features/comp/SearchUserBox.js';
 import {initInstall} from './features/install.js';
@@ -179,7 +179,7 @@ $(document).ready(() => {
   initRepoPullRequestAllowMaintainerEdit();
   initRepoPullRequestReview();
   initRepoRelease();
-  initRepoReleaseEditor();
+  initRepoReleaseNew();
   initRepoSettingGitHook();
   initRepoSettingSearchTeamBox();
   initRepoSettingsCollaboration();