-

- {{ctx.Locale.Tr "new_repo"}} -

-
- {{template "base/alert" .}} - {{template "repo/create_helper" .}} +

+ {{ctx.Locale.Tr "new_repo"}} +

+
+ {{template "base/alert" .}} + {{template "repo/create_helper" .}}
{{.CsrfTokenHtml}}
-
- +
+ - {{ctx.Locale.Tr "repo.owner_helper"}} -
-
- - +
+ + {{ctx.Locale.Tr "repo.repo_name_helper"}} {{ctx.Locale.Tr "repo.repo_name_profile_public_hint"}} {{ctx.Locale.Tr "repo.repo_name_profile_private_hint"}} -
- -
- -
- {{if .IsForcedPrivate}} - - - {{else}} - - - {{end}}
- {{ctx.Locale.Tr "repo.visibility_description"}} -
-
- - -
-
- - -
-
- +
- - + {{if .IsForcedPrivate}} + + + {{else}} + + + {{end}}
-
- - + {{ctx.Locale.Tr "repo.visibility_description"}} +
+
+ + +
+ + {{if .devstar_template_name}} +
+ + + {{ctx.Locale.Tr "repo.devstar_template_desc" "https://DevStar.cn/"}} +
+ {{end}} + +
+
+ + +
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+ + +
+
+ + +
+
+
+ +
+ + +
+
+ + +
+
+
+ +
+ + +
+
+ +
+
+ + +
+ +
+ +
+ + + {{ctx.Locale.Tr "repo.repo_gitignore_helper_desc"}} +
+
+ + + {{ctx.Locale.Tr "repo.license_helper_desc" "https://choosealicense.com/"}} +
+ +
+ + + {{ctx.Locale.Tr "repo.readme_helper_desc"}} +
+
+ +
+ + +
+
+
+ + + {{ctx.Locale.Tr "repo.default_branch_helper"}} +
+
+ + + {{ctx.Locale.Tr "repo.object_format_helper"}} +
+
+ +
+ + +
+
+
+
-
- - -
-
- - -
+
-
- -
- - -
-
- - -
-
-
- -
- - -
-
-
- -
-
- - -
- -
- -
- - - {{ctx.Locale.Tr "repo.repo_gitignore_helper_desc"}} -
-
- - - {{ctx.Locale.Tr "repo.license_helper_desc" "https://choosealicense.com/"}} -
- -
- - - {{ctx.Locale.Tr "repo.readme_helper_desc"}} -
-
- -
- - -
-
-
- - - {{ctx.Locale.Tr "repo.default_branch_helper"}} -
-
- - - {{ctx.Locale.Tr "repo.object_format_helper"}} -
-
- -
- - -
-
-
-
-
- -
diff --git a/web_src/js/features/repo-template.ts b/web_src/js/features/repo-template.ts new file mode 100644 index 0000000000..9113a3f121 --- /dev/null +++ b/web_src/js/features/repo-template.ts @@ -0,0 +1,187 @@ +import $ from 'jquery'; + +import { htmlEscape } from '../utils/html.ts'; +import { hideElem, showElem } from '../utils/dom.ts'; + +const {appSubUrl} = window.config; + +export function initRepoTemplateSearch() { + + function isValidGitUrl(url) { + // 正则表达式支持两种格式的 Git URL + const regex = /^https:\/\/([a-zA-Z0-9.-]+)\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)(\/commit\/([a-f0-9]{40}))?$/; + // 或者,以 .git 结尾 + const regexWithGit = /^https:\/\/([a-zA-Z0-9.-]+)\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)\.git$/; + return regex.test(url) || regexWithGit.test(url); + } + + function getRepoNameFromGitUrl(url) { + // 正则表达式支持两种格式的 Git URL + const regexWithCommit = /^https:\/\/([a-zA-Z0-9.-]+)\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)\/commit\/([a-f0-9]{40})$/; // 针对 commit ID 的 URL + const regexWithoutCommit = /^https:\/\/([a-zA-Z0-9.-]+)\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)\.git$/; // 针对 .git 结尾的 URL + // 尝试匹配 commit URL + let match = url.match(regexWithCommit); + if (match) { + return match[3]; // 返回 repo-name + } + // 尝试匹配 .git URL + match = url.match(regexWithoutCommit); + if (match) { + return match[3]; // 返回 repo-name + } + return null; // 如果没有匹配,返回 null + } + + const $repoTemplate = $('#repo_template'); + const $devstarTemplate = $('#devstar_template'); + const $gitURLTemplate = $('#git_url_template'); + const $templateUnits = $('#template_units'); + const $nonTemplate = $('#non_template'); + const $repoTemplateArea = $('#repo_template_area'); + const $gitURLTemplateArea = $('#git_url_template_area'); + const $devstarTemplateArea = $('#devstar_template_area'); + + const isDevstar = /^(https?:\/\/)?(www\.)?(devstar\.cn)(:\d+)?(\/.*)?$/i.test(document.URL); + if (isDevstar) { + hideElem($devstarTemplateArea); + $devstarTemplateArea.remove(); + } + + const GitURL = document.URL.match(/[?&]template_url=([^&]*)/); + if (GitURL) { + if (isValidGitUrl(GitURL[1])) { + $gitURLTemplate.val(GitURL[1]); + } + $devstarTemplateArea.val(''); + hideElem($devstarTemplateArea); + hideElem($repoTemplateArea); + } + + const template_id = document.URL.match(/[?&]template_id=([^&]*)/); + if (template_id) { + $devstarTemplateArea.val(''); + hideElem($devstarTemplateArea); + $gitURLTemplate.val(""); + hideElem($gitURLTemplateArea); + } + + const checkTemplate = function () { + if ($repoTemplate.val() !== '' && $repoTemplate.val() !== '0') { + showElem($templateUnits); + hideElem($nonTemplate); + hideElem($gitURLTemplateArea); + $devstarTemplateArea.val(''); + hideElem($devstarTemplateArea); + } else { + showElem($devstarTemplateArea); + hideElem($templateUnits); + showElem($nonTemplate); + showElem($gitURLTemplateArea); + } + }; + $repoTemplate.on('change', checkTemplate); + checkTemplate(); + + const checkGitURLTemplate = function () { + if ($gitURLTemplate.val() !== '' && $gitURLTemplate.val() !== '0') { + if ($('#repo_name').val() == '') { + $('#repo_name').val(getRepoNameFromGitUrl($gitURLTemplate.val())); + } + if ($('#description').val() == '') { + $('#description').val("init repo from " + $gitURLTemplate.val()); + } + hideElem($repoTemplateArea); + hideElem($nonTemplate); + $devstarTemplateArea.val(''); + hideElem($devstarTemplateArea); + } else { + showElem($devstarTemplateArea); + showElem($repoTemplateArea); + } + }; + if($gitURLTemplate.length){ + $gitURLTemplate.on('change', checkGitURLTemplate); + checkGitURLTemplate(); + } + + const checkDevStarTemplate = function () { + if ($devstarTemplate.val() !== '' && $devstarTemplate.val() !== '0') { + if ($('#repo_name').val() == '') { + $('#repo_name').val(getRepoNameFromGitUrl($devstarTemplate.val())); + } + if ($('#description').val() == '') { + $('#description').val("init repo from " + $devstarTemplate.val()); + } + $repoTemplate.val(''); + hideElem($gitURLTemplateArea); + hideElem($repoTemplateArea); + hideElem($nonTemplate); + } else { + showElem($repoTemplateArea); + showElem($gitURLTemplateArea); + hideElem($templateUnits); + showElem($nonTemplate); + } + }; + if($devstarTemplate.length){ + $devstarTemplate.on('change', checkDevStarTemplate); + } + + const initDevStarTemplateSearch = function () { + $('#devstar_template_search') + .dropdown({ + apiSettings: { + url: `https://devstar.cn/api/v1/repos/search?q={query}&template=true`, + onResponse(response) { + console.log(response.data); + const filteredResponse = { success: true, results: [] }; + filteredResponse.results.push({ + name: '-----', + value: '', + }); + // Parse the response from the api to work with our dropdown + $.each(response.data, (_r, repo) => { + filteredResponse.results.push({ + name: htmlEscape("DevStar.cn/" + repo.full_name), + value: repo.clone_url, + }); + }); + return filteredResponse; + }, + cache: true, + }, + + fullTextSearch: true, + }); + }; + initDevStarTemplateSearch(); + + const changeOwner = function () { + $('#repo_template_search') + .dropdown({ + apiSettings: { + url: `${appSubUrl}/repo/search?q={query}&template=true&priority_owner_id=${$('#uid').val()}`, + onResponse(response) { + const filteredResponse = { success: true, results: [] }; + filteredResponse.results.push({ + name: '-----', + value: '', + }); + // Parse the response from the api to work with our dropdown + $.each(response.data, (_r, repo) => { + filteredResponse.results.push({ + name: htmlEscape(repo.repository.full_name), + value: repo.repository.id, + }); + }); + return filteredResponse; + }, + cache: false, + }, + + fullTextSearch: true, + }); + }; + $('#uid').on('change', changeOwner); + changeOwner(); +} diff --git a/web_src/js/index-domready.ts b/web_src/js/index-domready.ts index 770c7fc00c..b86196980d 100644 --- a/web_src/js/index-domready.ts +++ b/web_src/js/index-domready.ts @@ -66,6 +66,7 @@ import {initGlobalButtonClickOnEnter, initGlobalButtons, initGlobalDeleteButton} import {initGlobalComboMarkdownEditor, initGlobalEnterQuickSubmit, initGlobalFormDirtyLeaveConfirm} from './features/common-form.ts'; import {callInitFunctions} from './modules/init.ts'; import {initRepoViewFileTree} from './features/repo-view-file-tree.ts'; +import {initRepoTemplateSearch} from './features/repo-template.ts'; const initStartTime = performance.now(); const initPerformanceTracer = callInitFunctions([ @@ -164,6 +165,7 @@ const initPerformanceTracer = callInitFunctions([ initOAuth2SettingsDisableCheckbox, initRepoFileView, + initRepoTemplateSearch, ]); // it must be the last one, then the "querySelectorAll" only needs to be executed once for global init functions.