summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/issuable_index.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/issuable_index.js')
-rw-r--r--app/assets/javascripts/issuable_index.js171
1 files changed, 171 insertions, 0 deletions
diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js
new file mode 100644
index 00000000000..5c96646def8
--- /dev/null
+++ b/app/assets/javascripts/issuable_index.js
@@ -0,0 +1,171 @@
+/* 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 IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
+import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
+
+((global) => {
+ var issuable_created;
+
+ issuable_created = false;
+
+ global.IssuableIndex = {
+ 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 = {
+ 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);