var SmartAnnotation = (function() { 'use strict'; // utilities var Util = (function() { // helper method that binds show/hidden action function showHideBinding() { $.each(['show', 'hide'], function (i, ev) { var el = $.fn[ev]; $.fn[ev] = function () { this.trigger(ev); return el.apply(this, arguments); }; }); } var publicApi = { showHideBinding: showHideBinding }; return publicApi; })(); // stop the user annotation popover on click propagation function atwhoStopPropagation(element) { $(element).on('click', function(e) { e.stopPropagation(); e.preventDefault(); }); } function setAtWho(field) { var FilterTypeEnum = Object.freeze({ USER: {tag: "users", dataUrl: $(document.body).attr('data-atwho-users-url')}, TASK: {tag: "sa-tasks", dataUrl: $(document.body).attr('data-atwho-task-url')}, PROJECT: {tag: "sa-projects", dataUrl: $(document.body).attr('data-atwho-project-url')}, EXPERIMENT: {tag: "sa-experiments", dataUrl: $(document.body).attr('data-atwho-experiment-url')}, REPOSITORY: {tag: "sa-repositories", dataUrl: $(document.body).attr('data-atwho-rep-items-url')}, MENU: {tag: "menu", dataUrl: $(document.body).attr('data-atwho-menu-items')} }); var prevAt, // Default selected filter when using '#' DEFAULT_SEARCH_FILTER = FilterTypeEnum.REPOSITORY, atWhoUpdating = false; function _matchHighlighter(html, query, filterType) { var $html = $(html); var $li_text = $html.find('.item-text'); if ($li_text.length === 0 || !query) return html; $.each($li_text, function(i, item) { $(item).html($(item).text().replace(new RegExp(query, 'gi'), '$&')); }) return $html; } function _generateInputTag(value, li) { return `[#${li.attr('data-name')}~${li.attr('data-type')}~${li.attr('data-id')}]`; } // Generates suggestion dropdown filter function generateFilterMenu(active, res_data) { var menu = ''; $.ajax({ async: false, dataType: 'json', url: $(document.body).attr('data-atwho-repositories-url'), success: function(data) { menu = data.html } }); return menu; } function atWhoSettings(at, defaultFilterType) { return { at: at, callbacks: { remoteFilter: function(query, callback) { var $currentAtWho = $('#' + $(field).data('smart-annotation')); var filterType; var params = { query: query }; filterType = FilterTypeEnum[$currentAtWho.find('.tab-pane.active').data('object-type')] if (!filterType) { callback([{name: ''}]); return false } if(filterType.tag === 'sa-repositories') { let repositoryTab = $currentAtWho.find('[data-object-type="REPOSITORY"]') let activeRepository = repositoryTab.find('.btn-primary'); if (activeRepository.length) { params['repository_id'] = activeRepository.data('object-id') } } $.getJSON(filterType.dataUrl, params, function(data) { localStorage.setItem('smart_annotation_state_per_team/' + data.team, JSON.stringify({ tag: filterType.tag, repository: data.repository })); callback(data.res); if (data.repository) { $currentAtWho.find(`.repository-object[data-object-id="${data.repository}"]`) .addClass('btn-primary').removeClass('btn-light') } }); }, tplEval: function(_tpl, items) { return items.name; }, highlighter: function(li, query) { return _matchHighlighter(li, query, true); return li; }, beforeInsert: function(value, li) { return _generateInputTag(value, li); }, matcher:function(flag, subtext, should_startWithSpace, acceptSpaceBar) { var _a, _y, match, regexp, space; flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); if (should_startWithSpace) { flag = '(?:^|\\s)' + flag; } _a = decodeURI("%C3%80"); _y = decodeURI("%C3%BF"); regexp = new RegExp(flag + "([A-Za-z" + _a + "-" + _y + "0-9_/:\\s\+\-\]*)$|" + flag + "([^\\x00-\\xff]*)$", 'gi'); match = regexp.exec(subtext); if (match) { return match[2] || match[1]; } else { return null; } }, }, headerTpl: generateFilterMenu(defaultFilterType), limit: <%= Constants::ATWHO_SEARCH_LIMIT %>, startWithSpace: true, acceptSpaceBar: true, displayTimeout: 120000 } } function init() { $(field) .on("shown.atwho", function() { var $currentAtWho = $('.atwho-view[style]:not(.old)'); $currentAtWho.addClass('old'); $(field).data('smart-annotation', $currentAtWho.attr('id')); $currentAtWho.find('.tab-button').off().on('shown.bs.tab', function() { $(field).click().focus(); $(this).closest('.nav-tabs').find('.tab-button').removeClass('active'); $(this).addClass('active'); }) $currentAtWho.find('.repository-object').off().on('click', function() { $(this).parent().find('.repository-object').removeClass('btn-primary').addClass('btn-light'); $(this).addClass('btn-primary').removeClass('btn-light'); $(field).click().focus(); }) if ($currentAtWho.find('.tab-pane.active').length == 0) { let filterType = DEFAULT_SEARCH_FILTER.tag; let teamId = $currentAtWho.find('.atwho-header-res').data('team-id'); let remeberedState = localStorage.getItem('smart_annotation_state_per_team/' + teamId); if (remeberedState) { remeberedState = JSON.parse(remeberedState); filterType = remeberedState.tag; $currentAtWho.find(`.repository-object[data-object-id=${remeberedState.repository}]`) .addClass('btn-primary'); } $currentAtWho.find(`.${filterType}`).click(); } }) .on("reposition.atwho", function(event, flag, query) { let inputFieldLeft = query.$inputor.offset().left; if (inputFieldLeft > $(window).width()) { let leftPosition; if (inputFieldLeft < flag.left + $(window).scrollLeft()) { leftPosition = inputFieldLeft; } else { leftPosition = flag.left + $(window).scrollLeft(); } query.$el.find('.atwho-view').css('left', leftPosition + 'px'); } if ($('.repository-show').length) { query.$el.find('.atwho-view').css('top', flag.top + 'px'); } }) .atwho({ at: '@', callbacks: { remoteFilter: function(query, callback) { $.getJSON( FilterTypeEnum.USER.dataUrl, {query: query}, function(data) { if (data.users.length < 1) { callback([{no_results: 1}]); } else { callback(data.users); } initDismissButton($('.atwho-view[style]')); } ); }, sorter: function(query, items, _searchKey) { // Sorting is already done on server-side return items; }, tplEval: function(_tpl, map) { var res; try { if (map.no_results) { res = ''; } else { res = ''; res += '