diff --git a/app/assets/javascripts/app/controllers/layout_ref.js.coffee b/app/assets/javascripts/app/controllers/layout_ref.js.coffee index aef80a862..f34fe78df 100644 --- a/app/assets/javascripts/app/controllers/layout_ref.js.coffee +++ b/app/assets/javascripts/app/controllers/layout_ref.js.coffee @@ -375,7 +375,7 @@ class LayoutRefCommunicationReply extends App.ControllerContent for i in [0..100] setTimeout @updateUploadProgress, i*duration/100 , i - setTimeout (=> + setTimeout (=> callback() @renderAttachment(fileName, fileSize) ), duration @@ -584,7 +584,7 @@ class ImportWizard extends App.ControllerWizard @render() # wait 500 ms after the last user input before we check the link - @otrsLink.on 'input', _.debounce(@checkOtrsLink, 600) + @otrsLink.on 'input', _.debounce(@checkOtrsLink, 600) checkOtrsLink: (e) => if @otrsLink.val() is "" @@ -852,14 +852,14 @@ class highlightRef extends App.ControllerContent # containing the offsets and the highlight classes # # we have to check how it works with having open several tickets – it might break - # + # # if classes can be changed in the admin interface # we have to watch out to not end up with empty highlight classes storeHighlights: -> localStorage['highlights'] = @highlighter.serialize() # the colors is set via css classes (can't do it inline with rangy) - # thus we have to create a stylesheet if the colors + # thus we have to create a stylesheet if the colors # can be changed in the admin interface addClassApplier: (entry) -> @highlighter.addClassApplier rangy.createCssClassApplier(@highlightClassPrefix + entry.name) @@ -884,7 +884,7 @@ class highlightRef extends App.ControllerContent activate: -> selection = rangy.getSelection() - # if there's already something selected, + # if there's already something selected, # don't go into highlight mode # just toggle the selected if !selection.isCollapsed @@ -914,10 +914,10 @@ class highlightRef extends App.ControllerContent onMouseUp: (e) => @toggleHighlightAtSelection $(e.currentTarget).closest @articles.selector - # + # # toggle Highlight # ================ - # + # # - only works when the selection starts and ends inside an article # - clears highlights in selection # - or highlights the selection @@ -931,7 +931,7 @@ class highlightRef extends App.ControllerContent else @highlighter.highlightSelection @highlightClass, selection: selection - containerElementId: article.get(0).id + containerElementId: article.get(0).id # remove selection selection.removeAllRanges() @@ -1096,7 +1096,7 @@ class cluesRef extends App.ControllerContent showWindow: => @modalWindow.velocity - properties: + properties: scale: [1, 0.2] opacity: [1, 0] options: @@ -1105,7 +1105,7 @@ class cluesRef extends App.ControllerContent hideWindow: (callback) => @modalWindow.velocity - properties: + properties: scale: [0.2, 1] opacity: 0 options: @@ -1131,7 +1131,7 @@ class cluesRef extends App.ControllerContent if target.right + modal.width <= maxWidth left = target.right position = 'right' - else + else # place left left = target.left - modal.width position = 'left' @@ -1208,7 +1208,7 @@ class cluesRef extends App.ControllerContent getVisibleBoundingBox: (el) -> ### - getBoundingClientRect doesn't take + getBoundingClientRect doesn't take absolute-positioned child nodes into account ### @@ -1412,7 +1412,7 @@ class schedulersRef extends App.ControllerContent switch items.length when 1 then return items[0] when 2 then return "#{ items[0] } and #{ items[1] }" - else + else return "#{ items.slice(0, -1).join(', ') } and #{ items[items.length-1] }" App.Config.set( 'layout_ref/schedulers', schedulersRef, 'Routes' ) @@ -1431,11 +1431,22 @@ class InputsRef extends App.ControllerContent # selectable search searchableSelectObject = new App.SearchableSelect attribute: - name: 'project-name' - id: 'project-name-123' + name: 'project-name' + id: 'project-name-123' placeholder: 'Enter Project Name' - options: [{"value":0,"name":"Apple"},{"value":1,"name":"Microsoft","selected":true},{"value":2,"name":"Google"},{"value":3,"name":"Deutsche Bahn"},{"value":4,"name":"Sparkasse"},{"value":5,"name":"Deutsche Post"},{"value":6,"name":"Mitfahrzentrale"},{"value":7,"name":"Starbucks"},{"value":8,"name":"Mac Donalds"},{"value":9,"name":"Flixbus"},{"value":10,"name":"Betahaus"},{"value":11,"name":"Bruno Banani"},{"value":12,"name":"Alpina"},{"value":13,"name":"Samsung"},{"value":14,"name":"ChariTea"},{"value":15,"name":"fritz-kola"},{"value":16,"name":"Vitamin Water"},{"value":17,"name":"Znuny"},{"value":18,"name":"Max & Moritz"}] - @$('.searchableSelectPlaceholder').replaceWith( searchableSelectObject.el ) + options: [{"value":0,"name":"Apple"},{"value":1,"name":"Microsoft","selected":true},{"value":2,"name":"Google"},{"value":3,"name":"Deutsche Bahn"},{"value":4,"name":"Sparkasse"},{"value":5,"name":"Deutsche Post"},{"value":6,"name":"Mitfahrzentrale"},{"value":7,"name":"Starbucks"},{"value":8,"name":"Mac Donalds"},{"value":9,"name":"Flixbus"},{"value":10,"name":"Betahaus"},{"value":11,"name":"Bruno Banani"},{"value":12,"name":"Alpina"},{"value":13,"name":"Samsung"},{"value":14,"name":"ChariTea"},{"value":15,"name":"fritz-kola"},{"value":16,"name":"Vitamin Water"},{"value":17,"name":"Znuny"},{"value":18,"name":"Max & Moritz"}] + @$('.searchableSelectPlaceholder').replaceWith( searchableSelectObject.element() ) + + # selectable search + searchableAjaxSelectObject = new App.SearchableAjaxSelect + attribute: + name: 'user' + id: 'user-123' + placeholder: 'Enter User' + limt: 10 + object: 'User' + + @$('.searchableAjaxSelectPlaceholder').replaceWith( searchableAjaxSelectObject.element() ) # time and timeframe @$('.time').timepicker() @@ -1515,7 +1526,7 @@ class calendarSubscriptionsRef extends App.ControllerContent switch items.length when 1 then return items[0] when 2 then return "#{ items[0] } and #{ items[1] }" - else + else return "#{ items.slice(0, -1).join(', ') } and #{ items[items.length-1] }" diff --git a/app/assets/javascripts/app/lib/app_post/searchable_select.js.coffee b/app/assets/javascripts/app/lib/app_post/searchable_select.js.coffee index 9eae1d37c..3cbfc62fa 100644 --- a/app/assets/javascripts/app/lib/app_post/searchable_select.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/searchable_select.js.coffee @@ -26,7 +26,6 @@ class App.SearchableSelect extends Spine.Controller @render() render: -> - console.log "options", @options firstSelected = _.find @options.attribute.options, (option) -> option.selected if firstSelected diff --git a/app/assets/javascripts/app/lib/app_post/user_organization_autocompletion.js.coffee b/app/assets/javascripts/app/lib/app_post/user_organization_autocompletion.js.coffee index c870df54a..995abb241 100644 --- a/app/assets/javascripts/app/lib/app_post/user_organization_autocompletion.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/user_organization_autocompletion.js.coffee @@ -14,7 +14,7 @@ class App.UserOrganizationAutocompletion extends App.Controller @key = Math.floor( Math.random() * 999999 ).toString() if !@attribute.source - @attribute.source = @apiPath + '/search_user_org' + @attribute.source = @apiPath + '/search/user-organization' @build() element: => diff --git a/app/assets/javascripts/app/lib/app_post/z_searchable_ajax_select.js.coffee b/app/assets/javascripts/app/lib/app_post/z_searchable_ajax_select.js.coffee index 1ef08cd5e..3abaf241b 100644 --- a/app/assets/javascripts/app/lib/app_post/z_searchable_ajax_select.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/z_searchable_ajax_select.js.coffee @@ -3,12 +3,81 @@ class App.SearchableAjaxSelect extends App.SearchableSelect onInput: (event) => super - # send ajax request @query + # convert requested object + # e.g. Ticket to ticket or AnotherObject to another_object + objectString = underscored( @options.attribute.object ) - onAjaxResponse: (data) => + # create common accessors + @apiPath = App.Config.get('api_path') + + # create cache and cache key + @searchResultCache = @searchResultCache || {} + + @cacheKey = "#{objectString}+#{@query}" + + # use cache for search result + if @searchResultCache[@cacheKey] + return @onAjaxResponse( @searchResultCache[@cacheKey] ) + + # add timout for loader icon + clearTimeout @loaderTimeoutId + @loaderTimeoutId = setTimeout @showLoader, 1000 + + # start search request and update options + App.Ajax.request( + id: @options.attribute.id + type: 'GET' + url: "#{@apiPath}/search/#{objectString}" + data: + query: @query + limit: @options.attribute.limit + processData: true + success: @onAjaxResponse + ) + + onAjaxResponse: (data, status, xhr) => + + # clear timout and remove loader icon + clearTimeout @loaderTimeoutId + @el.removeClass('is-loading') + + # cache search result + @searchResultCache[@cacheKey] = data + + # load assets + App.Collection.loadAssets( data.assets ) + + # get options from search result + options = [] + for object in data.result + if object.type is 'Ticket' + ticket = App.Ticket.find( object.id ) + data = + name: "##{ticket.number} - #{ticket.title}" + value: ticket.id + options.push data + else if object.type is 'User' + user = App.User.find( object.id ) + data = + name: "#{user.displayName()}" + value: user.id + options.push data + else if object.type is 'Organization' + organization = App.Organization.find( object.id ) + data = + name: "#{organization.displayName()}" + value: organization.id + options.push data + + # fill template with gathered options @optionsList.html App.view('generic/searchable_select_options') - options: data + options: options + # refresh elements @refreshElements() - @filterByQuery @query \ No newline at end of file + # execute filter + @filterByQuery @query + + showLoader: => + @el.addClass('is-loading') diff --git a/app/assets/javascripts/app/views/generic/searchable_select_options.jst.eco b/app/assets/javascripts/app/views/generic/searchable_select_options.jst.eco index d255b2be6..bf6cf3fc2 100644 --- a/app/assets/javascripts/app/views/generic/searchable_select_options.jst.eco +++ b/app/assets/javascripts/app/views/generic/searchable_select_options.jst.eco @@ -1,3 +1,5 @@ -<% for option in @options: %> -