2022-01-29 05:00:11 +08:00
|
|
|
import $ from 'jquery';
|
|
|
|
import 'jquery.are-you-sure';
|
2021-10-17 01:28:04 +08:00
|
|
|
import {mqBinarySearch} from '../utils.js';
|
2022-12-24 00:03:11 +08:00
|
|
|
import {createDropzone} from './dropzone.js';
|
2021-10-17 01:28:04 +08:00
|
|
|
import {initCompColorPicker} from './comp/ColorPicker.js';
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
import {showGlobalErrorMessage} from '../bootstrap.js';
|
2022-08-05 18:08:29 +08:00
|
|
|
import {handleGlobalEnterQuickSubmit} from './comp/QuickSubmit.js';
|
2023-01-22 12:14:43 +08:00
|
|
|
import {svg} from '../svg.js';
|
2023-02-19 12:06:14 +08:00
|
|
|
import {hideElem, showElem, toggleElem} from '../utils/dom.js';
|
2021-10-17 01:28:04 +08:00
|
|
|
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
const {appUrl, csrfToken} = window.config;
|
2021-10-17 01:28:04 +08:00
|
|
|
|
|
|
|
export function initGlobalFormDirtyLeaveConfirm() {
|
|
|
|
// Warn users that try to leave a page after entering data into a form.
|
|
|
|
// Except on sign-in pages, and for forms marked as 'ignore-dirty'.
|
|
|
|
if ($('.user.signin').length === 0) {
|
|
|
|
$('form:not(.ignore-dirty)').areYouSure();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function initHeadNavbarContentToggle() {
|
|
|
|
const content = $('#navbar');
|
|
|
|
const toggle = $('#navbar-expand-toggle');
|
|
|
|
let isExpanded = false;
|
|
|
|
toggle.on('click', () => {
|
|
|
|
isExpanded = !isExpanded;
|
|
|
|
if (isExpanded) {
|
|
|
|
content.addClass('shown');
|
|
|
|
toggle.addClass('active');
|
|
|
|
} else {
|
|
|
|
content.removeClass('shown');
|
|
|
|
toggle.removeClass('active');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function initFootLanguageMenu() {
|
|
|
|
function linkLanguageAction() {
|
|
|
|
const $this = $(this);
|
2022-11-09 15:40:26 +08:00
|
|
|
$.get($this.data('url')).always(() => {
|
2021-10-17 01:28:04 +08:00
|
|
|
window.location.reload();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
$('.language-menu a[lang]').on('click', linkLanguageAction);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function initGlobalEnterQuickSubmit() {
|
2022-05-20 10:26:04 +08:00
|
|
|
$(document).on('keydown', '.js-quick-submit', (e) => {
|
|
|
|
if (((e.ctrlKey && !e.altKey) || e.metaKey) && (e.key === 'Enter')) {
|
|
|
|
handleGlobalEnterQuickSubmit(e.target);
|
|
|
|
return false;
|
2021-10-17 01:28:04 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function initGlobalButtonClickOnEnter() {
|
|
|
|
$(document).on('keypress', '.ui.button', (e) => {
|
|
|
|
if (e.keyCode === 13 || e.keyCode === 32) { // enter key or space bar
|
2023-02-21 21:36:53 +08:00
|
|
|
if (e.target.nodeName === 'BUTTON') return; // button already handles space&enter correctly
|
2021-10-17 01:28:04 +08:00
|
|
|
$(e.target).trigger('click');
|
2023-02-10 01:11:16 +08:00
|
|
|
e.preventDefault();
|
2021-10-17 01:28:04 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function initGlobalCommon() {
|
|
|
|
// Undo Safari emoji glitch fix at high enough zoom levels
|
|
|
|
if (navigator.userAgent.match('Safari')) {
|
|
|
|
$(window).resize(() => {
|
|
|
|
const px = mqBinarySearch('width', 0, 4096, 1, 'px');
|
|
|
|
const em = mqBinarySearch('width', 0, 1024, 0.01, 'em');
|
|
|
|
if (em * 16 * 1.25 - px <= -1) {
|
|
|
|
$('body').addClass('safari-above125');
|
|
|
|
} else {
|
|
|
|
$('body').removeClass('safari-above125');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Semantic UI modules.
|
2022-06-04 05:38:26 +08:00
|
|
|
const $uiDropdowns = $('.ui.dropdown');
|
2023-03-17 11:08:05 +08:00
|
|
|
|
|
|
|
// do not init "custom" dropdowns, "custom" dropdowns are managed by their own code.
|
|
|
|
$uiDropdowns.filter(':not(.custom)').dropdown({fullTextSearch: 'exact'});
|
|
|
|
|
|
|
|
// The "jump" means this dropdown is mainly used for "menu" purpose,
|
|
|
|
// clicking an item will jump to somewhere else or trigger an action/function.
|
|
|
|
// When a dropdown is used for non-refresh actions with tippy,
|
|
|
|
// it must have this "jump" class to hide the tippy when dropdown is closed.
|
2022-06-04 05:38:26 +08:00
|
|
|
$uiDropdowns.filter('.jump').dropdown({
|
2021-10-17 01:28:04 +08:00
|
|
|
action: 'hide',
|
|
|
|
onShow() {
|
2022-08-09 20:37:34 +08:00
|
|
|
// hide associated tooltip while dropdown is open
|
|
|
|
this._tippy?.hide();
|
|
|
|
this._tippy?.disable();
|
|
|
|
},
|
|
|
|
onHide() {
|
|
|
|
this._tippy?.enable();
|
2023-03-17 11:08:05 +08:00
|
|
|
|
|
|
|
// hide all tippy elements of items after a while. eg: use Enter to click "Copy Link" in the Issue Context Menu
|
|
|
|
setTimeout(() => {
|
|
|
|
const $dropdown = $(this);
|
|
|
|
if ($dropdown.dropdown('is hidden')) {
|
|
|
|
$(this).find('.menu > .item').each((_, item) => {
|
|
|
|
item._tippy?.hide();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}, 2000);
|
2021-10-17 01:28:04 +08:00
|
|
|
},
|
|
|
|
});
|
2023-03-17 11:08:05 +08:00
|
|
|
|
|
|
|
// special animations/popup-directions
|
|
|
|
$uiDropdowns.filter('.slide.up').dropdown({transition: 'slide up'});
|
|
|
|
$uiDropdowns.filter('.upward').dropdown({direction: 'upward'});
|
|
|
|
|
Use a general approch to improve a11y for all checkboxes and dropdowns. (#23542)
This PR follows #22599 and #23450
The major improvements:
1. The `aria-*.js` are totally transparent now, no need to call
`attachDropdownAria` explicitly anymore.
* It hooks the `$.fn.checkbox` and `$.fn.dropdown`, then our patch
works.
* It makes all dynamically generated checkbox/dropdown work with a11y
without any change
* eg: the `conversation.find('.dropdown').dropdown();` in `repo-diff.js`
2. Since it's totally transparent now, it could be easier to modify or
remove in the future.
3. It handles all selection labels as well (by onLabelCreate), so it
supports "multiple selection dropdown" now.
* It partially completes one of my TODOs: `TODO: multiple selection is
not supported yet.`
4. The code structure is clearer, code blocks are splitted into
different functions.
* The old `attachOneDropdownAria` was splitted into separate functions.
* It makes it easier to add more fine tunes in the future, and co-work
with contributors.
6. The code logic is similar as before, only two new parts:
1. the `ariaCheckboxFn` and `ariaDropdownFn` functions
2. the `onLabelCreate` and `updateSelectionLabel` functions
In `aria-dropdown.js` I had to mix jQuery and Vanilla JS somewhat, I
think the code is still understandable, otherwise the code would be much
more complex to read.
Thanks to fsologureng for the idea about "improving the 'delete icon'
with aria attributes".
If there is anything unclear or incorrect, feel free to ask and discuss,
or propose new PRs for it.
2023-03-22 10:52:01 +08:00
|
|
|
$('.ui.checkbox').checkbox();
|
2021-11-18 11:26:50 +08:00
|
|
|
|
2021-10-17 01:28:04 +08:00
|
|
|
$('.tabular.menu .item').tab();
|
|
|
|
$('.tabable.menu .item').tab();
|
|
|
|
|
|
|
|
$('.toggle.button').on('click', function () {
|
2023-02-19 12:06:14 +08:00
|
|
|
toggleElem($($(this).data('target')));
|
2021-10-17 01:28:04 +08:00
|
|
|
});
|
|
|
|
|
2022-08-11 11:54:34 +08:00
|
|
|
// prevent multiple form submissions on forms containing .loading-button
|
|
|
|
document.addEventListener('submit', (e) => {
|
|
|
|
const btn = e.target.querySelector('.loading-button');
|
|
|
|
if (!btn) return;
|
|
|
|
if (btn.classList.contains('loading')) return e.preventDefault();
|
|
|
|
btn.classList.add('loading');
|
2022-05-07 20:24:02 +08:00
|
|
|
});
|
2021-10-17 01:28:04 +08:00
|
|
|
}
|
|
|
|
|
2021-11-09 17:27:25 +08:00
|
|
|
export function initGlobalDropzone() {
|
2021-10-17 01:28:04 +08:00
|
|
|
// Dropzone
|
|
|
|
for (const el of document.querySelectorAll('.dropzone')) {
|
|
|
|
const $dropzone = $(el);
|
2021-11-09 17:27:25 +08:00
|
|
|
const _promise = createDropzone(el, {
|
2021-10-17 01:28:04 +08:00
|
|
|
url: $dropzone.data('upload-url'),
|
2021-10-21 15:37:43 +08:00
|
|
|
headers: {'X-Csrf-Token': csrfToken},
|
2021-10-17 01:28:04 +08:00
|
|
|
maxFiles: $dropzone.data('max-file'),
|
|
|
|
maxFilesize: $dropzone.data('max-size'),
|
|
|
|
acceptedFiles: (['*/*', ''].includes($dropzone.data('accepts'))) ? null : $dropzone.data('accepts'),
|
|
|
|
addRemoveLinks: true,
|
|
|
|
dictDefaultMessage: $dropzone.data('default-message'),
|
|
|
|
dictInvalidFileType: $dropzone.data('invalid-input-type'),
|
|
|
|
dictFileTooBig: $dropzone.data('file-too-big'),
|
|
|
|
dictRemoveFile: $dropzone.data('remove-file'),
|
|
|
|
timeout: 0,
|
|
|
|
thumbnailMethod: 'contain',
|
|
|
|
thumbnailWidth: 480,
|
|
|
|
thumbnailHeight: 480,
|
|
|
|
init() {
|
2022-06-26 03:49:56 +08:00
|
|
|
this.on('success', (file, data) => {
|
|
|
|
file.uuid = data.uuid;
|
2021-10-17 01:28:04 +08:00
|
|
|
const input = $(`<input id="${data.uuid}" name="files" type="hidden">`).val(data.uuid);
|
|
|
|
$dropzone.find('.files').append(input);
|
2023-01-19 13:33:40 +08:00
|
|
|
// Create a "Copy Link" element, to conveniently copy the image
|
|
|
|
// or file link as Markdown to the clipboard
|
2023-01-22 12:14:43 +08:00
|
|
|
const copyLinkElement = document.createElement('div');
|
2023-02-14 01:59:59 +08:00
|
|
|
copyLinkElement.className = 'gt-tc';
|
2023-01-22 12:14:43 +08:00
|
|
|
// The a element has a hardcoded cursor: pointer because the default is overridden by .dropzone
|
|
|
|
copyLinkElement.innerHTML = `<a href="#" style="cursor: pointer;">${svg('octicon-copy', 14, 'copy link')} Copy link</a>`;
|
2023-01-19 13:33:40 +08:00
|
|
|
copyLinkElement.addEventListener('click', (e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
let fileMarkdown = `[${file.name}](/attachments/${file.uuid})`;
|
|
|
|
if (file.type.startsWith('image/')) {
|
|
|
|
fileMarkdown = `!${fileMarkdown}`;
|
|
|
|
}
|
|
|
|
navigator.clipboard.writeText(fileMarkdown);
|
|
|
|
});
|
|
|
|
file.previewTemplate.appendChild(copyLinkElement);
|
2021-10-17 01:28:04 +08:00
|
|
|
});
|
|
|
|
this.on('removedfile', (file) => {
|
|
|
|
$(`#${file.uuid}`).remove();
|
|
|
|
if ($dropzone.data('remove-url')) {
|
|
|
|
$.post($dropzone.data('remove-url'), {
|
|
|
|
file: file.uuid,
|
2021-10-21 15:37:43 +08:00
|
|
|
_csrf: csrfToken,
|
2021-10-17 01:28:04 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function initGlobalLinkActions() {
|
2023-03-14 11:34:09 +08:00
|
|
|
function showDeletePopup(e) {
|
|
|
|
e.preventDefault();
|
2021-10-17 01:28:04 +08:00
|
|
|
const $this = $(this);
|
|
|
|
const dataArray = $this.data();
|
|
|
|
let filter = '';
|
|
|
|
if ($this.data('modal-id')) {
|
|
|
|
filter += `#${$this.data('modal-id')}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
const dialog = $(`.delete.modal${filter}`);
|
|
|
|
dialog.find('.name').text($this.data('name'));
|
|
|
|
for (const [key, value] of Object.entries(dataArray)) {
|
|
|
|
if (key && key.startsWith('data')) {
|
|
|
|
dialog.find(`.${key}`).text(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dialog.modal({
|
|
|
|
closable: false,
|
|
|
|
onApprove() {
|
|
|
|
if ($this.data('type') === 'form') {
|
2022-01-16 19:19:26 +08:00
|
|
|
$($this.data('form')).trigger('submit');
|
2021-10-17 01:28:04 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const postData = {
|
2021-10-21 15:37:43 +08:00
|
|
|
_csrf: csrfToken,
|
2021-10-17 01:28:04 +08:00
|
|
|
};
|
|
|
|
for (const [key, value] of Object.entries(dataArray)) {
|
|
|
|
if (key && key.startsWith('data')) {
|
2022-02-18 14:50:36 +08:00
|
|
|
postData[key.slice(4)] = value;
|
2021-10-17 01:28:04 +08:00
|
|
|
}
|
|
|
|
if (key === 'id') {
|
|
|
|
postData['id'] = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$.post($this.data('url'), postData).done((data) => {
|
|
|
|
window.location.href = data.redirect;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}).modal('show');
|
|
|
|
}
|
|
|
|
|
2023-03-14 11:34:09 +08:00
|
|
|
function showAddAllPopup(e) {
|
|
|
|
e.preventDefault();
|
2021-10-17 01:28:04 +08:00
|
|
|
const $this = $(this);
|
|
|
|
let filter = '';
|
|
|
|
if ($this.attr('id')) {
|
|
|
|
filter += `#${$this.attr('id')}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
const dialog = $(`.addall.modal${filter}`);
|
|
|
|
dialog.find('.name').text($this.data('name'));
|
|
|
|
|
|
|
|
dialog.modal({
|
|
|
|
closable: false,
|
|
|
|
onApprove() {
|
|
|
|
if ($this.data('type') === 'form') {
|
2022-01-16 19:19:26 +08:00
|
|
|
$($this.data('form')).trigger('submit');
|
2021-10-17 01:28:04 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$.post($this.data('url'), {
|
2021-10-21 15:37:43 +08:00
|
|
|
_csrf: csrfToken,
|
2021-10-17 01:28:04 +08:00
|
|
|
id: $this.data('id')
|
|
|
|
}).done((data) => {
|
|
|
|
window.location.href = data.redirect;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}).modal('show');
|
|
|
|
}
|
|
|
|
|
|
|
|
function linkAction(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
const $this = $(this);
|
|
|
|
const redirect = $this.data('redirect');
|
2022-11-26 04:58:20 +08:00
|
|
|
$this.prop('disabled', true);
|
2021-10-17 01:28:04 +08:00
|
|
|
$.post($this.data('url'), {
|
2021-10-21 15:37:43 +08:00
|
|
|
_csrf: csrfToken
|
2021-10-17 01:28:04 +08:00
|
|
|
}).done((data) => {
|
|
|
|
if (data.redirect) {
|
|
|
|
window.location.href = data.redirect;
|
|
|
|
} else if (redirect) {
|
|
|
|
window.location.href = redirect;
|
|
|
|
} else {
|
|
|
|
window.location.reload();
|
|
|
|
}
|
2022-11-26 04:58:20 +08:00
|
|
|
}).always(() => {
|
|
|
|
$this.prop('disabled', false);
|
2021-10-17 01:28:04 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helpers.
|
|
|
|
$('.delete-button').on('click', showDeletePopup);
|
|
|
|
$('.link-action').on('click', linkAction);
|
|
|
|
|
|
|
|
// FIXME: this function is only used once, and not common, not well designed. should be refactored later
|
|
|
|
$('.add-all-button').on('click', showAddAllPopup);
|
|
|
|
|
|
|
|
// FIXME: this is only used once, and should be replace with `link-action` instead
|
|
|
|
$('.undo-button').on('click', function () {
|
|
|
|
const $this = $(this);
|
2022-11-26 04:58:20 +08:00
|
|
|
$this.prop('disabled', true);
|
2021-10-17 01:28:04 +08:00
|
|
|
$.post($this.data('url'), {
|
2021-10-21 15:37:43 +08:00
|
|
|
_csrf: csrfToken,
|
2021-10-17 01:28:04 +08:00
|
|
|
id: $this.data('id')
|
|
|
|
}).done((data) => {
|
|
|
|
window.location.href = data.redirect;
|
2022-11-26 04:58:20 +08:00
|
|
|
}).always(() => {
|
|
|
|
$this.prop('disabled', false);
|
2021-10-17 01:28:04 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function initGlobalButtons() {
|
2023-03-14 11:34:09 +08:00
|
|
|
// There are many "cancel button" elements in modal dialogs, Fomantic UI expects they are button-like elements but never submit a form.
|
|
|
|
// However, Gitea misuses the modal dialog and put the cancel buttons inside forms, so we must prevent the form submission.
|
|
|
|
// There are a few cancel buttons in non-modal forms, and there are some dynamically created forms (eg: the "Edit Issue Content")
|
2023-03-24 16:37:56 +08:00
|
|
|
$(document).on('click', 'form button.ui.cancel.button', (e) => {
|
2023-03-14 11:34:09 +08:00
|
|
|
e.preventDefault();
|
|
|
|
});
|
|
|
|
|
|
|
|
$('.show-panel.button').on('click', function (e) {
|
|
|
|
e.preventDefault();
|
2023-02-19 12:06:14 +08:00
|
|
|
showElem($(this).data('panel'));
|
2021-10-17 01:28:04 +08:00
|
|
|
});
|
|
|
|
|
2023-03-14 11:34:09 +08:00
|
|
|
$('.hide-panel.button').on('click', function (e) {
|
2022-01-07 09:18:52 +08:00
|
|
|
// a `.hide-panel.button` can hide a panel, by `data-panel="selector"` or `data-panel-closest="selector"`
|
2023-03-14 11:34:09 +08:00
|
|
|
e.preventDefault();
|
2022-01-07 09:18:52 +08:00
|
|
|
let sel = $(this).attr('data-panel');
|
|
|
|
if (sel) {
|
2023-02-19 12:06:14 +08:00
|
|
|
hideElem($(sel));
|
2022-01-07 09:18:52 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
sel = $(this).attr('data-panel-closest');
|
|
|
|
if (sel) {
|
2023-02-19 12:06:14 +08:00
|
|
|
hideElem($(this).closest(sel));
|
2022-01-07 09:18:52 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// should never happen, otherwise there is a bug in code
|
|
|
|
alert('Nothing to hide');
|
2021-10-17 01:28:04 +08:00
|
|
|
});
|
|
|
|
|
2023-03-14 11:34:09 +08:00
|
|
|
$('.show-modal').on('click', function (e) {
|
|
|
|
e.preventDefault();
|
2022-02-10 04:28:55 +08:00
|
|
|
const modalDiv = $($(this).attr('data-modal'));
|
|
|
|
for (const attrib of this.attributes) {
|
|
|
|
if (!attrib.name.startsWith('data-modal-')) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const id = attrib.name.substring(11);
|
|
|
|
const target = modalDiv.find(`#${id}`);
|
|
|
|
if (target.is('input')) {
|
|
|
|
target.val(attrib.value);
|
|
|
|
} else {
|
|
|
|
target.text(attrib.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
modalDiv.modal('show');
|
|
|
|
const colorPickers = $($(this).attr('data-modal')).find('.color-picker');
|
2021-10-17 01:28:04 +08:00
|
|
|
if (colorPickers.length > 0) {
|
|
|
|
initCompColorPicker();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-03-14 11:34:09 +08:00
|
|
|
$('.delete-post.button').on('click', function (e) {
|
|
|
|
e.preventDefault();
|
2021-10-17 01:28:04 +08:00
|
|
|
const $this = $(this);
|
2022-02-10 04:28:55 +08:00
|
|
|
$.post($this.attr('data-request-url'), {
|
2021-10-21 15:37:43 +08:00
|
|
|
_csrf: csrfToken
|
2021-10-17 01:28:04 +08:00
|
|
|
}).done(() => {
|
2022-02-10 04:28:55 +08:00
|
|
|
window.location.href = $this.attr('data-done-url');
|
2021-10-17 01:28:04 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Too many users set their ROOT_URL to wrong value, and it causes a lot of problems:
|
|
|
|
* * Cross-origin API request without correct cookie
|
|
|
|
* * Incorrect href in <a>
|
|
|
|
* * ...
|
|
|
|
* So we check whether current URL starts with AppUrl(ROOT_URL).
|
|
|
|
* If they don't match, show a warning to users.
|
|
|
|
*/
|
|
|
|
export function checkAppUrl() {
|
|
|
|
const curUrl = window.location.href;
|
2022-07-27 17:19:10 +08:00
|
|
|
// some users visit "https://domain/gitea" while appUrl is "https://domain/gitea/", there should be no warning
|
|
|
|
if (curUrl.startsWith(appUrl) || `${curUrl}/` === appUrl) {
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
return;
|
|
|
|
}
|
2023-02-10 00:14:45 +08:00
|
|
|
showGlobalErrorMessage(`Your ROOT_URL in app.ini is "${appUrl}", it's unlikely matching the site you are visiting.
|
|
|
|
Mismatched ROOT_URL config causes wrong URL links for web UI/mail content/webhook notification.`);
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
}
|