Skip to content

Refactor repo-new.ts #33070

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions web_src/js/features/repo-new.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,53 @@
import {hideElem, showElem} from '../utils/dom.ts';
import {hideElem, showElem, toggleElem} from '../utils/dom.ts';
import {htmlEscape} from 'escape-goat';
import {fomanticQuery} from '../modules/fomantic/base.ts';

const {appSubUrl} = window.config;

function initRepoNewTemplateSearch(form: HTMLFormElement) {
const inputRepoOwnerUid = form.querySelector<HTMLInputElement>('#uid');
const elRepoTemplateDropdown = form.querySelector<HTMLInputElement>('#repo_template_search');
const inputRepoTemplate = form.querySelector<HTMLInputElement>('#repo_template');
const elTemplateUnits = form.querySelector('#template_units');
const elNonTemplate = form.querySelector('#non_template');
const checkTemplate = function () {
const hasSelectedTemplate = inputRepoTemplate.value !== '' && inputRepoTemplate.value !== '0';
toggleElem(elTemplateUnits, hasSelectedTemplate);
toggleElem(elNonTemplate, !hasSelectedTemplate);
};
inputRepoTemplate.addEventListener('change', checkTemplate);
checkTemplate();

const $dropdown = fomanticQuery(elRepoTemplateDropdown);
const onChangeOwner = function () {
$dropdown.dropdown('setting', {
apiSettings: {
url: `${appSubUrl}/repo/search?q={query}&template=true&priority_owner_id=${inputRepoOwnerUid.value}`,
onResponse(response) {
const results = [];
results.push({name: '', value: ''}); // empty item means not using template
for (const tmplRepo of response.data) {
results.push({
name: htmlEscape(tmplRepo.repository.full_name),
value: String(tmplRepo.repository.id),
});
}
$dropdown.fomanticExt.onResponseKeepSelectedItem($dropdown, inputRepoTemplate.value);
return {results};
},
cache: false,
},
});
};
inputRepoOwnerUid.addEventListener('change', onChangeOwner);
onChangeOwner();
}

export function initRepoNew() {
const pageContent = document.querySelector('.page-content.repository.new-repo');
if (!pageContent) return;

const form = document.querySelector('.new-repo-form');
const form = document.querySelector<HTMLFormElement>('.new-repo-form');
const inputGitIgnores = form.querySelector<HTMLInputElement>('input[name="gitignores"]');
const inputLicense = form.querySelector<HTMLInputElement>('input[name="license"]');
const inputAutoInit = form.querySelector<HTMLInputElement>('input[name="auto_init"]');
Expand Down Expand Up @@ -32,4 +75,6 @@ export function initRepoNew() {
};
inputRepoName.addEventListener('input', updateUiRepoName);
updateUiRepoName();

initRepoNewTemplateSearch(form);
}
51 changes: 0 additions & 51 deletions web_src/js/features/repo-template.ts

This file was deleted.

3 changes: 2 additions & 1 deletion web_src/js/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ declare module 'swagger-ui-dist/swagger-ui-es-bundle.js' {
}

interface JQuery {
api: any, // fomantic
areYouSure: any, // jquery.are-you-sure
fomanticExt: any; // fomantic extension
api: any, // fomantic
dimmer: any, // fomantic
dropdown: any; // fomantic
modal: any; // fomantic
Expand Down
2 changes: 0 additions & 2 deletions web_src/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import {
import {initRepoEllipsisButton, initCommitStatuses} from './features/repo-commit.ts';
import {initRepoTopicBar} from './features/repo-home.ts';
import {initAdminCommon} from './features/admin/common.ts';
import {initRepoTemplateSearch} from './features/repo-template.ts';
import {initRepoCodeView} from './features/repo-code.ts';
import {initSshKeyFormParser} from './features/sshkey-helper.ts';
import {initUserSettings} from './features/user-settings.ts';
Expand Down Expand Up @@ -193,7 +192,6 @@ onDomReady(() => {
initRepoPullRequestReview,
initRepoRelease,
initRepoReleaseNew,
initRepoTemplateSearch,
initRepoTopicBar,
initRepoWikiForm,
initRepository,
Expand Down
3 changes: 2 additions & 1 deletion web_src/js/modules/fomantic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import {svg} from '../svg.ts';
export const fomanticMobileScreen = window.matchMedia('only screen and (max-width: 767.98px)');

export function initGiteaFomantic() {
// our extensions
$.fn.fomanticExt = {};
// Silence fomantic's error logging when tabs are used without a target content element
$.fn.tab.settings.silent = true;

// By default, use "exact match" for full text search
$.fn.dropdown.settings.fullTextSearch = 'exact';
// Do not use "cursor: pointer" for dropdown labels
Expand Down
18 changes: 18 additions & 0 deletions web_src/js/modules/fomantic/dropdown.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import $ from 'jquery';
import {generateAriaId} from './base.ts';
import type {FomanticInitFunction} from '../../types.ts';
import {queryElems} from '../../utils/dom.ts';

const ariaPatchKey = '_giteaAriaPatchDropdown';
const fomanticDropdownFn = $.fn.dropdown;
Expand All @@ -9,6 +10,7 @@ const fomanticDropdownFn = $.fn.dropdown;
export function initAriaDropdownPatch() {
if ($.fn.dropdown === ariaDropdownFn) throw new Error('initAriaDropdownPatch could only be called once');
$.fn.dropdown = ariaDropdownFn;
$.fn.fomanticExt.onResponseKeepSelectedItem = onResponseKeepSelectedItem;
(ariaDropdownFn as FomanticInitFunction).settings = fomanticDropdownFn.settings;
}

Expand Down Expand Up @@ -351,3 +353,19 @@ export function hideScopedEmptyDividers(container: Element) {
if (item.nextElementSibling?.matches('.divider')) hideDivider(item);
}
}

function onResponseKeepSelectedItem(dropdown: typeof $|HTMLElement, selectedValue: string) {
// There is a bug in fomantic dropdown when using "apiSettings" to fetch data
// * when there is a selected item, the dropdown insists on hiding the selected one from the list:
// * in the "filter" function: ('[data-value="'+value+'"]').addClass(className.filtered)
//
// When user selects one item, and click the dropdown again,
// then the dropdown only shows other items and will select another (wrong) one.
// It can't be easily fix by using setTimeout(patch, 0) in `onResponse` because the `onResponse` is called before another `setTimeout(..., timeLeft)`
// Fortunately, the "timeLeft" is controlled by "loadingDuration" which is always zero at the moment, so we can use `setTimeout(..., 10)`
const elDropdown = (dropdown instanceof HTMLElement) ? dropdown : dropdown[0];
setTimeout(() => {
queryElems(elDropdown, `.menu .item[data-value="${CSS.escape(selectedValue)}"].filtered`, (el) => el.classList.remove('filtered'));
$(elDropdown).dropdown('set selected', selectedValue ?? '');
}, 10);
}
Loading