debian-mirror-gitlab/app/assets/javascripts/issuable/issuable_form.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

199 lines
6 KiB
JavaScript
Raw Normal View History

2018-05-09 12:01:36 +05:30
import $ from 'jquery';
2017-09-10 17:25:29 +05:30
import Pikaday from 'pikaday';
2019-07-31 22:56:46 +05:30
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
2022-01-26 12:08:38 +05:30
import Autosave from '~/autosave';
import { parsePikadayDate, pikadayToString } from '~/lib/utils/datetime_utility';
import { queryToObject, objectToQuery } from '~/lib/utils/url_utility';
import UsersSelect from '~/users_select';
import ZenMode from '~/zen_mode';
2023-06-20 00:43:36 +05:30
import { containsSensitiveToken, confirmSensitiveAction, i18n } from '~/lib/utils/secret_detection';
2020-01-01 13:55:28 +05:30
2020-03-13 15:44:24 +05:30
const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
const MR_TARGET_BRANCH = 'merge_request[target_branch]';
2022-06-21 17:19:12 +05:30
const DATA_ISSUES_NEW_PATH = 'data-new-issue-path';
2020-03-13 15:44:24 +05:30
2023-06-20 00:43:36 +05:30
export function organizeQuery(obj, isFallbackKey = false) {
2020-03-13 15:44:24 +05:30
if (!obj[MR_SOURCE_BRANCH] && !obj[MR_TARGET_BRANCH]) {
return obj;
}
2020-01-01 13:55:28 +05:30
if (isFallbackKey) {
return {
2020-03-13 15:44:24 +05:30
[MR_SOURCE_BRANCH]: obj[MR_SOURCE_BRANCH],
2020-01-01 13:55:28 +05:30
};
}
return {
2020-03-13 15:44:24 +05:30
[MR_SOURCE_BRANCH]: obj[MR_SOURCE_BRANCH],
[MR_TARGET_BRANCH]: obj[MR_TARGET_BRANCH],
2020-01-01 13:55:28 +05:30
};
}
function format(searchTerm, isFallbackKey = false) {
2021-09-04 01:27:46 +05:30
const queryObject = queryToObject(searchTerm, { legacySpacesDecode: true });
2020-01-01 13:55:28 +05:30
const organizeQueryObject = organizeQuery(queryObject, isFallbackKey);
const formattedQuery = objectToQuery(organizeQueryObject);
return formattedQuery;
}
2022-10-11 01:57:18 +05:30
function getSearchTerm(newIssuePath) {
const { search, pathname } = document.location;
return newIssuePath === pathname ? '' : format(search);
}
2020-01-01 13:55:28 +05:30
function getFallbackKey() {
const searchTerm = format(document.location.search, true);
return ['autosave', document.location.pathname, searchTerm].join('/');
}
2018-03-17 18:26:18 +05:30
export default class IssuableForm {
2023-03-17 16:20:25 +05:30
static addAutosave(map, id, element, searchTerm, fallbackKey) {
if (!element) return;
map.set(
id,
new Autosave(element, [document.location.pathname, searchTerm, id], `${fallbackKey}=${id}`),
);
2022-10-11 01:57:18 +05:30
}
2018-03-17 18:26:18 +05:30
constructor(form) {
2022-07-23 23:45:48 +05:30
if (form.length === 0) {
return;
}
2018-03-17 18:26:18 +05:30
this.form = form;
this.resetAutosave = this.resetAutosave.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
2021-10-27 15:23:28 +05:30
// prettier-ignore
this.draftRegex = new RegExp(
2020-10-24 23:57:45 +05:30
'^\\s*(' + // Line start, then any amount of leading whitespace
2021-11-18 22:05:49 +05:30
'\\[draft\\]\\s*' + // [Draft] and any following whitespace
2021-10-27 15:23:28 +05:30
'|draft:\\s*' + // Draft: and any following whitespace
2021-03-08 18:12:59 +05:30
'|\\(draft\\)\\s*' + // (Draft) and any following whitespace
2021-10-27 15:23:28 +05:30
')+' + // At least one repeated match of the preceding parenthetical
'\\s*', // Any amount of trailing whitespace
2020-10-24 23:57:45 +05:30
'i', // Match any case(s)
);
2018-03-17 18:26:18 +05:30
2018-12-13 13:39:08 +05:30
this.gfmAutoComplete = new GfmAutoComplete(
gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources,
).setup();
2022-08-13 15:12:31 +05:30
this.usersSelect = new UsersSelect();
2020-11-24 15:15:51 +05:30
this.reviewersSelect = new UsersSelect(undefined, '.js-reviewer-search');
2018-12-13 13:39:08 +05:30
this.zenMode = new ZenMode();
2018-03-17 18:26:18 +05:30
2022-10-11 01:57:18 +05:30
this.searchTerm = getSearchTerm(form[0].getAttribute(DATA_ISSUES_NEW_PATH));
this.fallbackKey = getFallbackKey();
2018-03-17 18:26:18 +05:30
this.titleField = this.form.find('input[name*="[title]"]');
2023-06-20 00:43:36 +05:30
this.descriptionField = () => this.form.find('textarea[name*="[description]"]');
this.submitButton = this.form.find('.js-issuable-submit-button');
2023-04-23 21:23:45 +05:30
this.draftCheck = document.querySelector('input.js-toggle-draft');
2023-06-20 00:43:36 +05:30
if (!this.titleField.length) return;
2016-09-13 17:45:13 +05:30
2022-10-11 01:57:18 +05:30
this.autosaves = this.initAutosave();
2018-03-17 18:26:18 +05:30
this.form.on('submit', this.handleSubmit);
2022-08-13 15:12:31 +05:30
this.form.on('click', '.btn-cancel, .js-reset-autosave', this.resetAutosave);
2023-04-23 21:23:45 +05:30
this.initDraft();
2018-03-17 18:26:18 +05:30
const $issuableDueDate = $('#issuable-due-date');
if ($issuableDueDate.length) {
const calendar = new Pikaday({
field: $issuableDueDate.get(0),
2023-06-20 00:43:36 +05:30
theme: 'gl-datepicker-theme animate-picker',
2018-03-17 18:26:18 +05:30
format: 'yyyy-mm-dd',
container: $issuableDueDate.parent().get(0),
2021-03-08 18:12:59 +05:30
parse: (dateString) => parsePikadayDate(dateString),
toString: (date) => pikadayToString(date),
2022-10-11 01:57:18 +05:30
onSelect: (dateText) => {
$issuableDueDate.val(calendar.toString(dateText));
if (this.autosaves.has('due_date')) this.autosaves.get('due_date').save();
},
2019-03-02 22:35:43 +05:30
firstDay: gon.first_day_of_week,
2018-03-17 18:26:18 +05:30
});
calendar.setDate(parsePikadayDate($issuableDueDate.val()));
2016-09-13 17:45:13 +05:30
}
2018-03-17 18:26:18 +05:30
}
initAutosave() {
2022-10-11 01:57:18 +05:30
const autosaveMap = new Map();
IssuableForm.addAutosave(
autosaveMap,
'title',
2023-03-17 16:20:25 +05:30
this.form.find('input[name*="[title]"]').get(0),
2022-10-11 01:57:18 +05:30
this.searchTerm,
this.fallbackKey,
2020-01-01 13:55:28 +05:30
);
2022-10-11 01:57:18 +05:30
IssuableForm.addAutosave(
autosaveMap,
'confidential',
2023-03-17 16:20:25 +05:30
this.form.find('input:checkbox[name*="[confidential]"]').get(0),
2022-10-11 01:57:18 +05:30
this.searchTerm,
this.fallbackKey,
2020-01-01 13:55:28 +05:30
);
2022-10-11 01:57:18 +05:30
IssuableForm.addAutosave(
autosaveMap,
'due_date',
2023-03-17 16:20:25 +05:30
this.form.find('input[name*="[due_date]"]').get(0),
2022-10-11 01:57:18 +05:30
this.searchTerm,
this.fallbackKey,
);
return autosaveMap;
2018-03-17 18:26:18 +05:30
}
2023-06-20 00:43:36 +05:30
async handleSubmit(event) {
event.preventDefault();
const form = event.target;
const descriptionText = this.descriptionField().val();
if (containsSensitiveToken(descriptionText)) {
const confirmed = await confirmSensitiveAction(i18n.descriptionPrompt);
if (!confirmed) {
this.submitButton.removeAttr('disabled');
this.submitButton.removeClass('disabled');
return false;
}
}
form.submit();
2018-03-17 18:26:18 +05:30
return this.resetAutosave();
}
resetAutosave() {
2022-10-11 01:57:18 +05:30
this.autosaves.forEach((autosaveItem) => {
autosaveItem?.reset();
});
2018-03-17 18:26:18 +05:30
}
2023-04-23 21:23:45 +05:30
initDraft() {
if (this.draftCheck) {
this.draftCheck.addEventListener('click', () => this.writeDraftStatus());
this.titleField.on('keyup blur', () => this.readDraftStatus());
this.readDraftStatus();
2018-03-17 18:26:18 +05:30
}
}
2023-04-23 21:23:45 +05:30
isMarkedDraft() {
2021-10-27 15:23:28 +05:30
return this.draftRegex.test(this.titleField.val());
2018-03-17 18:26:18 +05:30
}
2023-04-23 21:23:45 +05:30
readDraftStatus() {
this.draftCheck.checked = this.isMarkedDraft();
2018-03-17 18:26:18 +05:30
}
2023-04-23 21:23:45 +05:30
writeDraftStatus() {
if (this.draftCheck.checked) {
this.addDraft();
2018-03-17 18:26:18 +05:30
} else {
2023-04-23 21:23:45 +05:30
this.removeDraft();
2018-03-17 18:26:18 +05:30
}
}
2023-04-23 21:23:45 +05:30
removeDraft() {
2021-10-27 15:23:28 +05:30
return this.titleField.val(this.titleField.val().replace(this.draftRegex, ''));
2018-03-17 18:26:18 +05:30
}
2023-04-23 21:23:45 +05:30
addDraft() {
2020-10-24 23:57:45 +05:30
this.titleField.val(`Draft: ${this.titleField.val()}`);
2018-03-17 18:26:18 +05:30
}
}