Merge branch '38869-importer_status' into 'master'
Remove code from global namespace See merge request gitlab-org/gitlab-ce!15058
This commit is contained in:
commit
2d5c4532f1
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable comma-dangle, space-before-function-paren, no-new */
|
/* eslint-disable comma-dangle, space-before-function-paren, no-new */
|
||||||
/* global IssuableContext */
|
|
||||||
/* global MilestoneSelect */
|
/* global MilestoneSelect */
|
||||||
/* global LabelsSelect */
|
/* global LabelsSelect */
|
||||||
/* global Sidebar */
|
/* global Sidebar */
|
||||||
|
@ -11,6 +10,7 @@ import AssigneeTitle from '../../sidebar/components/assignees/assignee_title';
|
||||||
import Assignees from '../../sidebar/components/assignees/assignees';
|
import Assignees from '../../sidebar/components/assignees/assignees';
|
||||||
import DueDateSelectors from '../../due_date_select';
|
import DueDateSelectors from '../../due_date_select';
|
||||||
import './sidebar/remove_issue';
|
import './sidebar/remove_issue';
|
||||||
|
import IssuableContext from '../../issuable_context';
|
||||||
|
|
||||||
const Store = gl.issueBoards.BoardsStore;
|
const Store = gl.issueBoards.BoardsStore;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len */
|
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len */
|
||||||
/* global ProjectSelect */
|
/* global ProjectSelect */
|
||||||
/* global IssuableIndex */
|
import IssuableIndex from './issuable_index';
|
||||||
/* global Milestone */
|
/* global Milestone */
|
||||||
/* global IssuableForm */
|
import IssuableForm from './issuable_form';
|
||||||
/* global LabelsSelect */
|
/* global LabelsSelect */
|
||||||
/* global MilestoneSelect */
|
/* global MilestoneSelect */
|
||||||
/* global NewBranchForm */
|
/* global NewBranchForm */
|
||||||
|
@ -173,7 +173,7 @@ import Diff from './diff';
|
||||||
filteredSearchManager.setup();
|
filteredSearchManager.setup();
|
||||||
}
|
}
|
||||||
const pagePrefix = page === 'projects:merge_requests:index' ? 'merge_request_' : 'issue_';
|
const pagePrefix = page === 'projects:merge_requests:index' ? 'merge_request_' : 'issue_';
|
||||||
IssuableIndex.init(pagePrefix);
|
new IssuableIndex(pagePrefix);
|
||||||
|
|
||||||
shortcut_handler = new ShortcutsNavigation();
|
shortcut_handler = new ShortcutsNavigation();
|
||||||
new UsersSelect();
|
new UsersSelect();
|
||||||
|
|
|
@ -1,83 +1,81 @@
|
||||||
/* eslint-disable func-names, space-before-function-paren, wrap-iife, camelcase, no-var, one-var, one-var-declaration-per-line, prefer-template, quotes, object-shorthand, comma-dangle, no-unused-vars, prefer-arrow-callback, no-else-return, vars-on-top, no-new, max-len */
|
class ImporterStatus {
|
||||||
|
constructor(jobsUrl, importUrl) {
|
||||||
|
this.jobsUrl = jobsUrl;
|
||||||
|
this.importUrl = importUrl;
|
||||||
|
this.initStatusPage();
|
||||||
|
this.setAutoUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
(function() {
|
initStatusPage() {
|
||||||
window.ImporterStatus = (function() {
|
$('.js-add-to-import')
|
||||||
function ImporterStatus(jobs_url, import_url) {
|
.off('click')
|
||||||
this.jobs_url = jobs_url;
|
.on('click', (event) => {
|
||||||
this.import_url = import_url;
|
const $btn = $(event.currentTarget);
|
||||||
this.initStatusPage();
|
const $tr = $btn.closest('tr');
|
||||||
this.setAutoUpdate();
|
const $targetField = $tr.find('.import-target');
|
||||||
}
|
const $namespaceInput = $targetField.find('.js-select-namespace option:selected');
|
||||||
|
const id = $tr.attr('id').replace('repo_', '');
|
||||||
ImporterStatus.prototype.initStatusPage = function() {
|
let targetNamespace;
|
||||||
$('.js-add-to-import').off('click').on('click', (function(_this) {
|
let newName;
|
||||||
return function(e) {
|
if ($namespaceInput.length > 0) {
|
||||||
var $btn, $namespace_input, $target_field, $tr, id, target_namespace, newName;
|
targetNamespace = $namespaceInput[0].innerHTML;
|
||||||
$btn = $(e.currentTarget);
|
newName = $targetField.find('#path').prop('value');
|
||||||
$tr = $btn.closest('tr');
|
$targetField.empty().append(`${targetNamespace}/${newName}`);
|
||||||
$target_field = $tr.find('.import-target');
|
}
|
||||||
$namespace_input = $target_field.find('.js-select-namespace option:selected');
|
|
||||||
id = $tr.attr('id').replace('repo_', '');
|
|
||||||
target_namespace = null;
|
|
||||||
newName = null;
|
|
||||||
if ($namespace_input.length > 0) {
|
|
||||||
target_namespace = $namespace_input[0].innerHTML;
|
|
||||||
newName = $target_field.find('#path').prop('value');
|
|
||||||
$target_field.empty().append(target_namespace + "/" + newName);
|
|
||||||
}
|
|
||||||
$btn.disable().addClass('is-loading');
|
|
||||||
return $.post(_this.import_url, {
|
|
||||||
repo_id: id,
|
|
||||||
target_namespace: target_namespace,
|
|
||||||
new_name: newName
|
|
||||||
}, {
|
|
||||||
dataType: 'script'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
})(this));
|
|
||||||
return $('.js-import-all').off('click').on('click', function(e) {
|
|
||||||
var $btn;
|
|
||||||
$btn = $(this);
|
|
||||||
$btn.disable().addClass('is-loading');
|
$btn.disable().addClass('is-loading');
|
||||||
return $('.js-add-to-import').each(function() {
|
|
||||||
|
return $.post(this.importUrl, {
|
||||||
|
repo_id: id,
|
||||||
|
target_namespace: targetNamespace,
|
||||||
|
new_name: newName,
|
||||||
|
}, {
|
||||||
|
dataType: 'script',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.js-import-all')
|
||||||
|
.off('click')
|
||||||
|
.on('click', function onClickImportAll() {
|
||||||
|
const $btn = $(this);
|
||||||
|
$btn.disable().addClass('is-loading');
|
||||||
|
return $('.js-add-to-import').each(function triggerAddImport() {
|
||||||
return $(this).trigger('click');
|
return $(this).trigger('click');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
ImporterStatus.prototype.setAutoUpdate = function() {
|
setAutoUpdate() {
|
||||||
return setInterval(((function(_this) {
|
return setInterval(() => $.get(this.jobsUrl, data => $.each(data, (i, job) => {
|
||||||
return function() {
|
const jobItem = $(`#project_${job.id}`);
|
||||||
return $.get(_this.jobs_url, function(data) {
|
const statusField = jobItem.find('.job-status');
|
||||||
return $.each(data, function(i, job) {
|
|
||||||
var job_item, status_field;
|
|
||||||
job_item = $("#project_" + job.id);
|
|
||||||
status_field = job_item.find(".job-status");
|
|
||||||
if (job.import_status === 'finished') {
|
|
||||||
job_item.removeClass("active").addClass("success");
|
|
||||||
return status_field.html('<span><i class="fa fa-check"></i> done</span>');
|
|
||||||
} else if (job.import_status === 'scheduled') {
|
|
||||||
return status_field.html("<i class='fa fa-spinner fa-spin'></i> scheduled");
|
|
||||||
} else if (job.import_status === 'started') {
|
|
||||||
return status_field.html("<i class='fa fa-spinner fa-spin'></i> started");
|
|
||||||
} else {
|
|
||||||
return status_field.html(job.import_status);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
})(this)), 4000);
|
|
||||||
};
|
|
||||||
|
|
||||||
return ImporterStatus;
|
const spinner = '<i class="fa fa-spinner fa-spin"></i>';
|
||||||
})();
|
|
||||||
|
|
||||||
$(function() {
|
switch (job.import_status) {
|
||||||
if ($('.js-importer-status').length) {
|
case 'finished':
|
||||||
var jobsImportPath = $('.js-importer-status').data('jobs-import-path');
|
jobItem.removeClass('active').addClass('success');
|
||||||
var importPath = $('.js-importer-status').data('import-path');
|
statusField.html('<span><i class="fa fa-check"></i> done</span>');
|
||||||
|
break;
|
||||||
|
case 'scheduled':
|
||||||
|
statusField.html(`${spinner} scheduled`);
|
||||||
|
break;
|
||||||
|
case 'started':
|
||||||
|
statusField.html(`${spinner} started`);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
statusField.html(job.import_status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})), 4000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
new window.ImporterStatus(jobsImportPath, importPath);
|
// eslint-disable-next-line consistent-return
|
||||||
}
|
export default function initImporterStatus() {
|
||||||
});
|
const importerStatus = document.querySelector('.js-importer-status');
|
||||||
}).call(window);
|
|
||||||
|
if (importerStatus) {
|
||||||
|
const data = importerStatus.dataset;
|
||||||
|
return new ImporterStatus(data.jobsImportPath, data.importPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* eslint-disable no-new */
|
/* eslint-disable no-new */
|
||||||
/* global MilestoneSelect */
|
/* global MilestoneSelect */
|
||||||
/* global LabelsSelect */
|
/* global LabelsSelect */
|
||||||
/* global IssuableContext */
|
import IssuableContext from './issuable_context';
|
||||||
/* global Sidebar */
|
/* global Sidebar */
|
||||||
|
|
||||||
import DueDateSelectors from './due_date_select';
|
import DueDateSelectors from './due_date_select';
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, space-before-function-paren, prefer-arrow-callback, max-len, no-unused-expressions, no-sequences, no-underscore-dangle, no-unused-vars, no-param-reassign */
|
/* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, space-before-function-paren, prefer-arrow-callback, max-len, no-unused-expressions, no-sequences, no-underscore-dangle, no-unused-vars, no-param-reassign */
|
||||||
/* global IssuableIndex */
|
|
||||||
import _ from 'underscore';
|
import _ from 'underscore';
|
||||||
import Flash from './flash';
|
import Flash from './flash';
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
/* global SubscriptionSelect */
|
/* global SubscriptionSelect */
|
||||||
|
|
||||||
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
|
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
|
||||||
|
import './milestone_select';
|
||||||
|
import './issue_status_select';
|
||||||
|
import './subscription_select';
|
||||||
|
import './labels_select';
|
||||||
|
|
||||||
const HIDDEN_CLASS = 'hidden';
|
const HIDDEN_CLASS = 'hidden';
|
||||||
const DISABLED_CONTENT_CLASS = 'disabled-content';
|
const DISABLED_CONTENT_CLASS = 'disabled-content';
|
||||||
|
|
|
@ -1,33 +1,35 @@
|
||||||
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, comma-dangle, quotes, prefer-arrow-callback, consistent-return, one-var, no-var, one-var-declaration-per-line, no-underscore-dangle, max-len */
|
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
import bp from './breakpoints';
|
import bp from './breakpoints';
|
||||||
import UsersSelect from './users_select';
|
import UsersSelect from './users_select';
|
||||||
|
|
||||||
const PARTICIPANTS_ROW_COUNT = 7;
|
const PARTICIPANTS_ROW_COUNT = 7;
|
||||||
|
|
||||||
(function() {
|
export default class IssuableContext {
|
||||||
this.IssuableContext = (function() {
|
constructor(currentUser) {
|
||||||
function IssuableContext(currentUser) {
|
this.initParticipants();
|
||||||
this.initParticipants();
|
this.userSelect = new UsersSelect(currentUser);
|
||||||
new UsersSelect(currentUser);
|
|
||||||
$('select.select2').select2({
|
$('select.select2').select2({
|
||||||
width: 'resolve',
|
width: 'resolve',
|
||||||
dropdownAutoWidth: true
|
dropdownAutoWidth: true,
|
||||||
});
|
});
|
||||||
$(".issuable-sidebar .inline-update").on("change", "select", function() {
|
|
||||||
return $(this).submit();
|
$('.issuable-sidebar .inline-update').on('change', 'select', function onClickSelect() {
|
||||||
});
|
return $(this).submit();
|
||||||
$(".issuable-sidebar .inline-update").on("change", ".js-assignee", function() {
|
});
|
||||||
return $(this).submit();
|
$('.issuable-sidebar .inline-update').on('change', '.js-assignee', function onClickAssignee() {
|
||||||
});
|
return $(this).submit();
|
||||||
$(document).off('click', '.issuable-sidebar .dropdown-content a').on('click', '.issuable-sidebar .dropdown-content a', function(e) {
|
});
|
||||||
return e.preventDefault();
|
$(document)
|
||||||
});
|
.off('click', '.issuable-sidebar .dropdown-content a')
|
||||||
$(document).off('click', '.edit-link').on('click', '.edit-link', function(e) {
|
.on('click', '.issuable-sidebar .dropdown-content a', e => e.preventDefault());
|
||||||
var $block, $selectbox;
|
|
||||||
|
$(document)
|
||||||
|
.off('click', '.edit-link')
|
||||||
|
.on('click', '.edit-link', function onClickEdit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$block = $(this).parents('.block');
|
const $block = $(this).parents('.block');
|
||||||
$selectbox = $block.find('.selectbox');
|
const $selectbox = $block.find('.selectbox');
|
||||||
if ($selectbox.is(':visible')) {
|
if ($selectbox.is(':visible')) {
|
||||||
$selectbox.hide();
|
$selectbox.hide();
|
||||||
$block.find('.value').show();
|
$block.find('.value').show();
|
||||||
|
@ -35,46 +37,43 @@ const PARTICIPANTS_ROW_COUNT = 7;
|
||||||
$selectbox.show();
|
$selectbox.show();
|
||||||
$block.find('.value').hide();
|
$block.find('.value').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($selectbox.is(':visible')) {
|
if ($selectbox.is(':visible')) {
|
||||||
return setTimeout(function() {
|
setTimeout(() => $block.find('.dropdown-menu-toggle').trigger('click'), 0);
|
||||||
return $block.find('.dropdown-menu-toggle').trigger('click');
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
window.addEventListener('beforeunload', function() {
|
|
||||||
// collapsed_gutter cookie hides the sidebar
|
|
||||||
var bpBreakpoint = bp.getBreakpointSize();
|
|
||||||
if (bpBreakpoint === 'xs' || bpBreakpoint === 'sm') {
|
|
||||||
Cookies.set('collapsed_gutter', true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', () => {
|
||||||
|
// collapsed_gutter cookie hides the sidebar
|
||||||
|
const bpBreakpoint = bp.getBreakpointSize();
|
||||||
|
if (bpBreakpoint === 'xs' || bpBreakpoint === 'sm') {
|
||||||
|
Cookies.set('collapsed_gutter', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initParticipants() {
|
||||||
|
$(document).on('click', '.js-participants-more', this.toggleHiddenParticipants);
|
||||||
|
return $('.js-participants-author').each(function forEachAuthor(i) {
|
||||||
|
if (i >= PARTICIPANTS_ROW_COUNT) {
|
||||||
|
$(this).addClass('js-participants-hidden').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleHiddenParticipants() {
|
||||||
|
const currentText = $(this).text().trim();
|
||||||
|
const lessText = $(this).data('less-text');
|
||||||
|
const originalText = $(this).data('original-text');
|
||||||
|
|
||||||
|
if (currentText === originalText) {
|
||||||
|
$(this).text(lessText);
|
||||||
|
|
||||||
|
if (gl.lazyLoader) gl.lazyLoader.loadCheck();
|
||||||
|
} else {
|
||||||
|
$(this).text(originalText);
|
||||||
}
|
}
|
||||||
|
|
||||||
IssuableContext.prototype.initParticipants = function() {
|
$('.js-participants-hidden').toggle();
|
||||||
$(document).on('click', '.js-participants-more', this.toggleHiddenParticipants);
|
}
|
||||||
return $('.js-participants-author').each(function(i) {
|
}
|
||||||
if (i >= PARTICIPANTS_ROW_COUNT) {
|
|
||||||
return $(this).addClass('js-participants-hidden').hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
IssuableContext.prototype.toggleHiddenParticipants = function() {
|
|
||||||
const currentText = $(this).text().trim();
|
|
||||||
const lessText = $(this).data('less-text');
|
|
||||||
const originalText = $(this).data('original-text');
|
|
||||||
|
|
||||||
if (currentText === originalText) {
|
|
||||||
$(this).text(lessText);
|
|
||||||
|
|
||||||
if (gl.lazyLoader) gl.lazyLoader.loadCheck();
|
|
||||||
} else {
|
|
||||||
$(this).text(originalText);
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.js-participants-hidden').toggle();
|
|
||||||
};
|
|
||||||
|
|
||||||
return IssuableContext;
|
|
||||||
})();
|
|
||||||
}).call(window);
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, no-use-before-define, no-useless-escape, no-new, quotes, object-shorthand, no-unused-vars, comma-dangle, no-alert, consistent-return, no-else-return, prefer-template, one-var, one-var-declaration-per-line, curly, max-len */
|
/* eslint-disable func-names, prefer-rest-params, wrap-iife, no-use-before-define, no-useless-escape, no-new, object-shorthand, no-unused-vars, comma-dangle, no-alert, consistent-return, no-else-return, prefer-template, one-var, one-var-declaration-per-line, curly, max-len */
|
||||||
/* global GitLab */
|
/* global GitLab */
|
||||||
|
|
||||||
import Pikaday from 'pikaday';
|
import Pikaday from 'pikaday';
|
||||||
|
@ -8,103 +8,100 @@ import GfmAutoComplete from './gfm_auto_complete';
|
||||||
import ZenMode from './zen_mode';
|
import ZenMode from './zen_mode';
|
||||||
import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
|
import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
|
||||||
|
|
||||||
(function() {
|
export default class IssuableForm {
|
||||||
this.IssuableForm = (function() {
|
constructor(form) {
|
||||||
IssuableForm.prototype.wipRegex = /^\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i;
|
this.form = form;
|
||||||
|
this.toggleWip = this.toggleWip.bind(this);
|
||||||
|
this.renderWipExplanation = this.renderWipExplanation.bind(this);
|
||||||
|
this.resetAutosave = this.resetAutosave.bind(this);
|
||||||
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
|
this.wipRegex = /^\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i;
|
||||||
|
|
||||||
function IssuableForm(form) {
|
new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources).setup();
|
||||||
var $issuableDueDate, calendar;
|
new UsersSelect();
|
||||||
this.form = form;
|
new ZenMode();
|
||||||
this.toggleWip = this.toggleWip.bind(this);
|
|
||||||
this.renderWipExplanation = this.renderWipExplanation.bind(this);
|
this.titleField = this.form.find('input[name*="[title]"]');
|
||||||
this.resetAutosave = this.resetAutosave.bind(this);
|
this.descriptionField = this.form.find('textarea[name*="[description]"]');
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
if (!(this.titleField.length && this.descriptionField.length)) {
|
||||||
new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources).setup();
|
return;
|
||||||
new UsersSelect();
|
|
||||||
new ZenMode();
|
|
||||||
this.titleField = this.form.find("input[name*='[title]']");
|
|
||||||
this.descriptionField = this.form.find("textarea[name*='[description]']");
|
|
||||||
if (!(this.titleField.length && this.descriptionField.length)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.initAutosave();
|
|
||||||
this.form.on("submit", this.handleSubmit);
|
|
||||||
this.form.on("click", ".btn-cancel", this.resetAutosave);
|
|
||||||
this.initWip();
|
|
||||||
$issuableDueDate = $('#issuable-due-date');
|
|
||||||
if ($issuableDueDate.length) {
|
|
||||||
calendar = new Pikaday({
|
|
||||||
field: $issuableDueDate.get(0),
|
|
||||||
theme: 'gitlab-theme animate-picker',
|
|
||||||
format: 'yyyy-mm-dd',
|
|
||||||
container: $issuableDueDate.parent().get(0),
|
|
||||||
parse: dateString => parsePikadayDate(dateString),
|
|
||||||
toString: date => pikadayToString(date),
|
|
||||||
onSelect: function(dateText) {
|
|
||||||
$issuableDueDate.val(calendar.toString(dateText));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
calendar.setDate(parsePikadayDate($issuableDueDate.val()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IssuableForm.prototype.initAutosave = function() {
|
this.initAutosave();
|
||||||
new Autosave(this.titleField, [document.location.pathname, document.location.search, "title"]);
|
this.form.on('submit', this.handleSubmit);
|
||||||
return new Autosave(this.descriptionField, [document.location.pathname, document.location.search, "description"]);
|
this.form.on('click', '.btn-cancel', this.resetAutosave);
|
||||||
};
|
this.initWip();
|
||||||
|
|
||||||
IssuableForm.prototype.handleSubmit = function() {
|
const $issuableDueDate = $('#issuable-due-date');
|
||||||
return this.resetAutosave();
|
|
||||||
};
|
|
||||||
|
|
||||||
IssuableForm.prototype.resetAutosave = function() {
|
if ($issuableDueDate.length) {
|
||||||
this.titleField.data("autosave").reset();
|
const calendar = new Pikaday({
|
||||||
return this.descriptionField.data("autosave").reset();
|
field: $issuableDueDate.get(0),
|
||||||
};
|
theme: 'gitlab-theme animate-picker',
|
||||||
|
format: 'yyyy-mm-dd',
|
||||||
|
container: $issuableDueDate.parent().get(0),
|
||||||
|
parse: dateString => parsePikadayDate(dateString),
|
||||||
|
toString: date => pikadayToString(date),
|
||||||
|
onSelect: dateText => $issuableDueDate.val(calendar.toString(dateText)),
|
||||||
|
});
|
||||||
|
calendar.setDate(parsePikadayDate($issuableDueDate.val()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IssuableForm.prototype.initWip = function() {
|
initAutosave() {
|
||||||
this.$wipExplanation = this.form.find(".js-wip-explanation");
|
new Autosave(this.titleField, [document.location.pathname, document.location.search, 'title']);
|
||||||
this.$noWipExplanation = this.form.find(".js-no-wip-explanation");
|
return new Autosave(this.descriptionField, [document.location.pathname, document.location.search, 'description']);
|
||||||
if (!(this.$wipExplanation.length && this.$noWipExplanation.length)) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.form.on("click", ".js-toggle-wip", this.toggleWip);
|
|
||||||
this.titleField.on("keyup blur", this.renderWipExplanation);
|
|
||||||
return this.renderWipExplanation();
|
|
||||||
};
|
|
||||||
|
|
||||||
IssuableForm.prototype.workInProgress = function() {
|
handleSubmit() {
|
||||||
return this.wipRegex.test(this.titleField.val());
|
return this.resetAutosave();
|
||||||
};
|
}
|
||||||
|
|
||||||
IssuableForm.prototype.renderWipExplanation = function() {
|
resetAutosave() {
|
||||||
if (this.workInProgress()) {
|
this.titleField.data('autosave').reset();
|
||||||
this.$wipExplanation.show();
|
return this.descriptionField.data('autosave').reset();
|
||||||
return this.$noWipExplanation.hide();
|
}
|
||||||
} else {
|
|
||||||
this.$wipExplanation.hide();
|
|
||||||
return this.$noWipExplanation.show();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
IssuableForm.prototype.toggleWip = function(event) {
|
initWip() {
|
||||||
event.preventDefault();
|
this.$wipExplanation = this.form.find('.js-wip-explanation');
|
||||||
if (this.workInProgress()) {
|
this.$noWipExplanation = this.form.find('.js-no-wip-explanation');
|
||||||
this.removeWip();
|
if (!(this.$wipExplanation.length && this.$noWipExplanation.length)) {
|
||||||
} else {
|
return;
|
||||||
this.addWip();
|
}
|
||||||
}
|
this.form.on('click', '.js-toggle-wip', this.toggleWip);
|
||||||
return this.renderWipExplanation();
|
this.titleField.on('keyup blur', this.renderWipExplanation);
|
||||||
};
|
return this.renderWipExplanation();
|
||||||
|
}
|
||||||
|
|
||||||
IssuableForm.prototype.removeWip = function() {
|
workInProgress() {
|
||||||
return this.titleField.val(this.titleField.val().replace(this.wipRegex, ""));
|
return this.wipRegex.test(this.titleField.val());
|
||||||
};
|
}
|
||||||
|
|
||||||
IssuableForm.prototype.addWip = function() {
|
renderWipExplanation() {
|
||||||
return this.titleField.val("WIP: " + (this.titleField.val()));
|
if (this.workInProgress()) {
|
||||||
};
|
this.$wipExplanation.show();
|
||||||
|
return this.$noWipExplanation.hide();
|
||||||
|
} else {
|
||||||
|
this.$wipExplanation.hide();
|
||||||
|
return this.$noWipExplanation.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return IssuableForm;
|
toggleWip(event) {
|
||||||
})();
|
event.preventDefault();
|
||||||
}).call(window);
|
if (this.workInProgress()) {
|
||||||
|
this.removeWip();
|
||||||
|
} else {
|
||||||
|
this.addWip();
|
||||||
|
}
|
||||||
|
return this.renderWipExplanation();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeWip() {
|
||||||
|
return this.titleField.val(this.titleField.val().replace(this.wipRegex, ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
addWip() {
|
||||||
|
this.titleField.val(`WIP: ${(this.titleField.val())}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,171 +1,42 @@
|
||||||
/* eslint-disable no-param-reassign, func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, wrap-iife, max-len */
|
|
||||||
/* global IssuableIndex */
|
|
||||||
import _ from 'underscore';
|
|
||||||
import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
|
import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
|
||||||
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
|
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
|
||||||
|
|
||||||
((global) => {
|
export default class IssuableIndex {
|
||||||
var issuable_created;
|
constructor(pagePrefix) {
|
||||||
|
this.initBulkUpdate(pagePrefix);
|
||||||
|
IssuableIndex.resetIncomingEmailToken();
|
||||||
|
}
|
||||||
|
initBulkUpdate(pagePrefix) {
|
||||||
|
const userCanBulkUpdate = $('.issues-bulk-update').length > 0;
|
||||||
|
const alreadyInitialized = !!this.bulkUpdateSidebar;
|
||||||
|
|
||||||
issuable_created = false;
|
if (userCanBulkUpdate && !alreadyInitialized) {
|
||||||
|
IssuableBulkUpdateActions.init({
|
||||||
global.IssuableIndex = {
|
prefixId: pagePrefix,
|
||||||
init: function(pagePrefix) {
|
|
||||||
IssuableIndex.initTemplates();
|
|
||||||
IssuableIndex.initSearch();
|
|
||||||
IssuableIndex.initBulkUpdate(pagePrefix);
|
|
||||||
IssuableIndex.initResetFilters();
|
|
||||||
IssuableIndex.resetIncomingEmailToken();
|
|
||||||
IssuableIndex.initLabelFilterRemove();
|
|
||||||
},
|
|
||||||
initTemplates: function() {
|
|
||||||
return IssuableIndex.labelRow = _.template('<% _.each(labels, function(label){ %> <span class="label-row btn-group" role="group" aria-label="<%- label.title %>" style="color: <%- label.text_color %>;"> <a href="#" class="btn btn-transparent has-tooltip" style="background-color: <%- label.color %>;" title="<%- label.description %>" data-container="body"> <%- label.title %> </a> <button type="button" class="btn btn-transparent label-remove js-label-filter-remove" style="background-color: <%- label.color %>;" data-label="<%- label.title %>"> <i class="fa fa-times"></i> </button> </span> <% }); %>');
|
|
||||||
},
|
|
||||||
initSearch: function() {
|
|
||||||
const $searchInput = $('#issuable_search');
|
|
||||||
|
|
||||||
IssuableIndex.initSearchState($searchInput);
|
|
||||||
|
|
||||||
// `immediate` param set to false debounces on the `trailing` edge, lets user finish typing
|
|
||||||
const debouncedExecSearch = _.debounce(IssuableIndex.executeSearch, 1000, false);
|
|
||||||
|
|
||||||
$searchInput.off('keyup').on('keyup', debouncedExecSearch);
|
|
||||||
|
|
||||||
// ensures existing filters are preserved when manually submitted
|
|
||||||
$('#issuable_search_form').on('submit', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
debouncedExecSearch(e);
|
|
||||||
});
|
});
|
||||||
},
|
|
||||||
initSearchState: function($searchInput) {
|
|
||||||
const currentSearchVal = $searchInput.val();
|
|
||||||
|
|
||||||
IssuableIndex.searchState = {
|
this.bulkUpdateSidebar = new IssuableBulkUpdateSidebar();
|
||||||
elem: $searchInput,
|
|
||||||
current: currentSearchVal
|
|
||||||
};
|
|
||||||
|
|
||||||
IssuableIndex.maybeFocusOnSearch();
|
|
||||||
},
|
|
||||||
accessSearchPristine: function(set) {
|
|
||||||
// store reference to previous value to prevent search on non-mutating keyup
|
|
||||||
const state = IssuableIndex.searchState;
|
|
||||||
const currentSearchVal = state.elem.val();
|
|
||||||
|
|
||||||
if (set) {
|
|
||||||
state.current = currentSearchVal;
|
|
||||||
} else {
|
|
||||||
return state.current === currentSearchVal;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
maybeFocusOnSearch: function() {
|
|
||||||
const currentSearchVal = IssuableIndex.searchState.current;
|
|
||||||
if (currentSearchVal && currentSearchVal !== '') {
|
|
||||||
const queryLength = currentSearchVal.length;
|
|
||||||
const $searchInput = IssuableIndex.searchState.elem;
|
|
||||||
|
|
||||||
/* The following ensures that the cursor is initially placed at
|
|
||||||
* the end of search input when focus is applied. It accounts
|
|
||||||
* for differences in browser implementations of `setSelectionRange`
|
|
||||||
* and cursor placement for elements in focus.
|
|
||||||
*/
|
|
||||||
$searchInput.focus();
|
|
||||||
if ($searchInput.setSelectionRange) {
|
|
||||||
$searchInput.setSelectionRange(queryLength, queryLength);
|
|
||||||
} else {
|
|
||||||
$searchInput.val(currentSearchVal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
executeSearch: function(e) {
|
|
||||||
const $search = $('#issuable_search');
|
|
||||||
const $searchName = $search.attr('name');
|
|
||||||
const $searchValue = $search.val();
|
|
||||||
const $filtersForm = $('.js-filter-form');
|
|
||||||
const $input = $(`input[name='${$searchName}']`, $filtersForm);
|
|
||||||
const isPristine = IssuableIndex.accessSearchPristine();
|
|
||||||
|
|
||||||
if (isPristine) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$input.length) {
|
|
||||||
$filtersForm.append(`<input type='hidden' name='${$searchName}' value='${_.escape($searchValue)}'/>`);
|
|
||||||
} else {
|
|
||||||
$input.val($searchValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
IssuableIndex.filterResults($filtersForm);
|
|
||||||
},
|
|
||||||
initLabelFilterRemove: function() {
|
|
||||||
return $(document).off('click', '.js-label-filter-remove').on('click', '.js-label-filter-remove', function(e) {
|
|
||||||
var $button;
|
|
||||||
$button = $(this);
|
|
||||||
// Remove the label input box
|
|
||||||
$('input[name="label_name[]"]').filter(function() {
|
|
||||||
return this.value === $button.data('label');
|
|
||||||
}).remove();
|
|
||||||
// Submit the form to get new data
|
|
||||||
IssuableIndex.filterResults($('.filter-form'));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
filterResults: (function(_this) {
|
|
||||||
return function(form) {
|
|
||||||
var formAction, formData, issuesUrl;
|
|
||||||
formData = form.serializeArray();
|
|
||||||
formData = formData.filter(function(data) {
|
|
||||||
return data.value !== '';
|
|
||||||
});
|
|
||||||
formData = $.param(formData);
|
|
||||||
formAction = form.attr('action');
|
|
||||||
issuesUrl = formAction;
|
|
||||||
issuesUrl += "" + (formAction.indexOf('?') === -1 ? '?' : '&');
|
|
||||||
issuesUrl += formData;
|
|
||||||
return gl.utils.visitUrl(issuesUrl);
|
|
||||||
};
|
|
||||||
})(this),
|
|
||||||
initResetFilters: function() {
|
|
||||||
$('.reset-filters').on('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const target = e.target;
|
|
||||||
const $form = $(target).parents('.js-filter-form');
|
|
||||||
const baseIssuesUrl = target.href;
|
|
||||||
|
|
||||||
$form.attr('action', baseIssuesUrl);
|
|
||||||
gl.utils.visitUrl(baseIssuesUrl);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
initBulkUpdate: function(pagePrefix) {
|
|
||||||
const userCanBulkUpdate = $('.issues-bulk-update').length > 0;
|
|
||||||
const alreadyInitialized = !!this.bulkUpdateSidebar;
|
|
||||||
|
|
||||||
if (userCanBulkUpdate && !alreadyInitialized) {
|
|
||||||
IssuableBulkUpdateActions.init({
|
|
||||||
prefixId: pagePrefix,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.bulkUpdateSidebar = new IssuableBulkUpdateSidebar();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resetIncomingEmailToken: function() {
|
|
||||||
$('.incoming-email-token-reset').on('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: 'PUT',
|
|
||||||
url: $('.incoming-email-token-reset').attr('href'),
|
|
||||||
dataType: 'json',
|
|
||||||
success: function(response) {
|
|
||||||
$('#issue_email').val(response.new_issue_address).focus();
|
|
||||||
},
|
|
||||||
beforeSend: function() {
|
|
||||||
$('.incoming-email-token-reset').text('resetting...');
|
|
||||||
},
|
|
||||||
complete: function() {
|
|
||||||
$('.incoming-email-token-reset').text('reset it');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
})(window);
|
|
||||||
|
static resetIncomingEmailToken() {
|
||||||
|
$('.incoming-email-token-reset').on('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: 'PUT',
|
||||||
|
url: $('.incoming-email-token-reset').attr('href'),
|
||||||
|
dataType: 'json',
|
||||||
|
success(response) {
|
||||||
|
$('#issue_email').val(response.new_issue_address).focus();
|
||||||
|
},
|
||||||
|
beforeSend() {
|
||||||
|
$('.incoming-email-token-reset').text('resetting...');
|
||||||
|
},
|
||||||
|
complete() {
|
||||||
|
$('.incoming-email-token-reset').text('reset it');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -55,9 +55,7 @@ import './gl_field_error';
|
||||||
import './gl_field_errors';
|
import './gl_field_errors';
|
||||||
import './gl_form';
|
import './gl_form';
|
||||||
import './header';
|
import './header';
|
||||||
import './importer_status';
|
import initImporterStatus from './importer_status';
|
||||||
import './issuable_index';
|
|
||||||
import './issuable_context';
|
|
||||||
import './issuable_form';
|
import './issuable_form';
|
||||||
import './issue';
|
import './issue';
|
||||||
import './issue_status_select';
|
import './issue_status_select';
|
||||||
|
@ -138,6 +136,7 @@ $(function () {
|
||||||
var fitSidebarForSize;
|
var fitSidebarForSize;
|
||||||
|
|
||||||
initBreadcrumbs();
|
initBreadcrumbs();
|
||||||
|
initImporterStatus();
|
||||||
|
|
||||||
// Set the default path for all cookies to GitLab's root directory
|
// Set the default path for all cookies to GitLab's root directory
|
||||||
Cookies.defaults.path = gon.relative_url_root || '/';
|
Cookies.defaults.path = gon.relative_url_root || '/';
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* global IssuableContext */
|
|
||||||
import '~/issuable_context';
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
import IssuableContext from '~/issuable_context';
|
||||||
|
|
||||||
describe('IssuableContext', () => {
|
describe('IssuableContext', () => {
|
||||||
describe('toggleHiddenParticipants', () => {
|
describe('toggleHiddenParticipants', () => {
|
||||||
|
|
|
@ -1,80 +1,44 @@
|
||||||
/* global IssuableIndex */
|
import IssuableIndex from '~/issuable_index';
|
||||||
|
|
||||||
import '~/lib/utils/url_utility';
|
describe('Issuable', () => {
|
||||||
import '~/issuable_index';
|
let Issuable;
|
||||||
|
describe('initBulkUpdate', () => {
|
||||||
(() => {
|
it('should not set bulkUpdateSidebar', () => {
|
||||||
const BASE_URL = '/user/project/issues?scope=all&state=closed';
|
Issuable = new IssuableIndex('issue_');
|
||||||
const DEFAULT_PARAMS = '&utf8=%E2%9C%93';
|
expect(Issuable.bulkUpdateSidebar).not.toBeDefined();
|
||||||
|
|
||||||
function updateForm(formValues, form) {
|
|
||||||
$.each(formValues, (id, value) => {
|
|
||||||
$(`#${id}`, form).val(value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetForm(form) {
|
|
||||||
$('input[name!="utf8"]', form).each((index, input) => {
|
|
||||||
input.setAttribute('value', '');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Issuable', () => {
|
|
||||||
preloadFixtures('static/issuable_filter.html.raw');
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
loadFixtures('static/issuable_filter.html.raw');
|
|
||||||
IssuableIndex.init();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be defined', () => {
|
it('should set bulkUpdateSidebar', () => {
|
||||||
expect(window.IssuableIndex).toBeDefined();
|
const element = document.createElement('div');
|
||||||
});
|
element.classList.add('issues-bulk-update');
|
||||||
|
document.body.appendChild(element);
|
||||||
|
|
||||||
describe('filtering', () => {
|
Issuable = new IssuableIndex('issue_');
|
||||||
let $filtersForm;
|
expect(Issuable.bulkUpdateSidebar).toBeDefined();
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
$filtersForm = $('.js-filter-form');
|
|
||||||
loadFixtures('static/issuable_filter.html.raw');
|
|
||||||
resetForm($filtersForm);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contain only the default parameters', () => {
|
|
||||||
spyOn(gl.utils, 'visitUrl');
|
|
||||||
|
|
||||||
IssuableIndex.filterResults($filtersForm);
|
|
||||||
|
|
||||||
expect(gl.utils.visitUrl).toHaveBeenCalledWith(BASE_URL + DEFAULT_PARAMS);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter for the phrase "broken"', () => {
|
|
||||||
spyOn(gl.utils, 'visitUrl');
|
|
||||||
|
|
||||||
updateForm({ search: 'broken' }, $filtersForm);
|
|
||||||
IssuableIndex.filterResults($filtersForm);
|
|
||||||
const params = `${DEFAULT_PARAMS}&search=broken`;
|
|
||||||
|
|
||||||
expect(gl.utils.visitUrl).toHaveBeenCalledWith(BASE_URL + params);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should keep query parameters after modifying filter', () => {
|
|
||||||
spyOn(gl.utils, 'visitUrl');
|
|
||||||
|
|
||||||
// initial filter
|
|
||||||
updateForm({ milestone_title: 'v1.0' }, $filtersForm);
|
|
||||||
|
|
||||||
IssuableIndex.filterResults($filtersForm);
|
|
||||||
let params = `${DEFAULT_PARAMS}&milestone_title=v1.0`;
|
|
||||||
expect(gl.utils.visitUrl).toHaveBeenCalledWith(BASE_URL + params);
|
|
||||||
|
|
||||||
// update filter
|
|
||||||
updateForm({ label_name: 'Frontend' }, $filtersForm);
|
|
||||||
|
|
||||||
IssuableIndex.filterResults($filtersForm);
|
|
||||||
params = `${DEFAULT_PARAMS}&milestone_title=v1.0&label_name=Frontend`;
|
|
||||||
expect(gl.utils.visitUrl).toHaveBeenCalledWith(BASE_URL + params);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})();
|
|
||||||
|
describe('resetIncomingEmailToken', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const element = document.createElement('a');
|
||||||
|
element.classList.add('incoming-email-token-reset');
|
||||||
|
element.setAttribute('href', 'foo');
|
||||||
|
document.body.appendChild(element);
|
||||||
|
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.setAttribute('id', 'issue_email');
|
||||||
|
document.body.appendChild(input);
|
||||||
|
|
||||||
|
Issuable = new IssuableIndex('issue_');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send request to reset email token', () => {
|
||||||
|
spyOn(jQuery, 'ajax').and.callThrough();
|
||||||
|
document.querySelector('.incoming-email-token-reset').click();
|
||||||
|
|
||||||
|
expect(jQuery.ajax).toHaveBeenCalled();
|
||||||
|
expect(jQuery.ajax.calls.argsFor(0)[0].url).toEqual('foo');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
/* eslint-disable no-new */
|
/* eslint-disable no-new */
|
||||||
/* global IssuableContext */
|
import IssuableContext from '~/issuable_context';
|
||||||
/* global LabelsSelect */
|
/* global LabelsSelect */
|
||||||
|
|
||||||
import '~/gl_dropdown';
|
import '~/gl_dropdown';
|
||||||
import 'select2';
|
import 'select2';
|
||||||
import '~/api';
|
import '~/api';
|
||||||
import '~/create_label';
|
import '~/create_label';
|
||||||
import '~/issuable_context';
|
|
||||||
import '~/users_select';
|
import '~/users_select';
|
||||||
import '~/labels_select';
|
import '~/labels_select';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue