Browse Source

Added tree selection attribute for object manager.

Martin Edenhofer 7 years ago
parent
commit
fb8130da18

+ 65 - 1
app/assets/javascripts/app/controllers/_ui_element/object_manager_attribute.coffee

@@ -15,7 +15,7 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
         attribute: attribute
         params: params
       ))
-      @[localParams.data_type](element, localParams, params)
+      @[localParams.data_type](element, localParams, params, attribute)
       localItem.find('.js-dataMap').html(element)
       localItem.find('.js-dataScreens').html(@dataScreens(attribute, localParams, params))
 
@@ -24,6 +24,7 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
       date: 'Date'
       input: 'Text'
       select: 'Select'
+      tree_select: 'Tree Select'
       boolean: 'Boolean'
       integer: 'Integer'
 
@@ -308,6 +309,69 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
       lastSelected = value
     )
 
+  @buildRow: (element, child, level = 0, parentElement) ->
+    newRow = element.find('.js-template').clone().removeClass('js-template')
+    newRow.find('.js-key').attr('level', level)
+    newRow.find('.js-key').val(child.name)
+    newRow.find('td').first().css('padding-left', "#{(level * 20) + 10}px")
+    if level is 5
+      newRow.find('.js-addChild').addClass('hide')
+
+    if parentElement
+      parentElement.after(newRow)
+      return
+
+    element.find('.js-treeTable').append(newRow)
+    if child.children
+      for subChild in child.children
+        @buildRow(element, subChild, level + 1)
+
+  @tree_select: (item, localParams, params, attribute) ->
+    params.data_option ||= {}
+    params.data_option.options ||= []
+    if _.isEmpty(params.data_option.options)
+      @buildRow(item, {})
+    else
+      for child in params.data_option.options
+        @buildRow(item, child)
+
+    item.on('click', '.js-addRow', (e) =>
+      e.stopPropagation()
+      e.preventDefault()
+      addRow = $(e.currentTarget).closest('tr')
+      level  = parseInt(addRow.find('.js-key').attr('level'))
+      @buildRow(item, {}, level, addRow)
+    )
+
+    item.on('click', '.js-addChild', (e) =>
+      e.stopPropagation()
+      e.preventDefault()
+      addRow = $(e.currentTarget).closest('tr')
+      level  = parseInt(addRow.find('.js-key').attr('level')) + 1
+      @buildRow(item, {}, level, addRow)
+    )
+
+    item.on('click', '.js-remove', (e) ->
+      e.stopPropagation()
+      e.preventDefault()
+      e.stopPro
+      element = $(e.target).closest('tr')
+      level  = parseInt(element.find('.js-key').attr('level'))
+      subElements = 0
+      nextElement = element
+      elementsToDelete = [element]
+      loop
+        nextElement = nextElement.next()
+        break if !nextElement.get(0)
+        nextLevel = parseInt(nextElement.find('.js-key').attr('level'))
+        break if nextLevel <= level
+        subElements += 1
+        elementsToDelete.push nextElement
+      return if subElements isnt 0 && !confirm("Delete #{subElements} sub elements?")
+      for element in elementsToDelete
+        element.remove()
+    )
+
   @boolean: (item, localParams, params) ->
     lastSelected = undefined
     item.on('click', '.js-selected', (e) ->

+ 8 - 8
app/assets/javascripts/app/controllers/_ui_element/searchable_select.coffee

@@ -9,24 +9,24 @@ class App.UiElement.searchable_select extends App.UiElement.ApplicationUiElement
       attribute.multiple = ''
 
     # build options list based on config
-    @getConfigOptionList( attribute, params )
+    @getConfigOptionList(attribute, params)
 
     # build options list based on relation
-    @getRelationOptionList( attribute, params )
+    @getRelationOptionList(attribute, params)
 
     # add null selection if needed
-    @addNullOption( attribute, params )
+    @addNullOption(attribute, params)
 
     # sort attribute.options
-    @sortOptions( attribute, params )
+    @sortOptions(attribute, params)
 
     # finde selected/checked item of list
-    @selectedOptions( attribute, params )
+    @selectedOptions(attribute, params)
 
     # disable item of list
-    @disabledOptions( attribute, params )
+    @disabledOptions(attribute, params)
 
     # filter attributes
-    @filterOption( attribute, params )
+    @filterOption(attribute, params)
 
-    new App.SearchableSelect( attribute: attribute ).element()
+    new App.SearchableSelect(attribute: attribute).element()

+ 41 - 0
app/assets/javascripts/app/controllers/_ui_element/tree_select.coffee

@@ -0,0 +1,41 @@
+# coffeelint: disable=camel_case_classes
+class App.UiElement.tree_select extends App.UiElement.ApplicationUiElement
+  @optionsSelect: (children, value) ->
+    return if !children
+    for child in children
+      if child.value is value
+        child.selected = true
+      if child.children
+        @optionsSelect(child.children, value)
+
+  @render: (attribute, params) ->
+
+    # set multiple option
+    if attribute.multiple
+      attribute.multiple = 'multiple'
+    else
+      attribute.multiple = ''
+
+    # build options list based on config
+    @getConfigOptionList(attribute, params)
+
+    # build options list based on relation
+    @getRelationOptionList(attribute, params)
+
+    # add null selection if needed
+    @addNullOption(attribute, params)
+
+    # sort attribute.options
+    @sortOptions(attribute, params)
+
+    # finde selected/checked item of list
+    if attribute.options
+      @optionsSelect(attribute.options, attribute.value)
+
+    # disable item of list
+    @disabledOptions(attribute, params)
+
+    # filter attributes
+    @filterOption(attribute, params)
+
+    new App.SearchableSelect(attribute: attribute).element()

+ 46 - 0
app/assets/javascripts/app/controllers/object_manager.coffee

@@ -1,4 +1,46 @@
 # coffeelint: disable=duplicate_key
+treeParams = (e, params) ->
+  tree = []
+  lastLevel = 0
+  lastLevels = []
+  valueLevels = []
+
+  $(e.target).closest('.modal').find('.js-treeTable .js-key').each( ->
+    $element = $(@)
+    level = parseInt($element.attr('level'))
+    name = $element.val()
+    item =
+      name: name
+
+    if level is 0
+      tree.push item
+    else if lastLevels[level-1]
+      lastLevels[level-1].children ||= []
+      lastLevels[level-1].children.push item
+    else
+      console.log('ERROR', item)
+    if level is 0
+      valueLevels = []
+    else if lastLevel is level
+      valueLevels.pop()
+    else if lastLevel > level
+      down = lastLevel - level
+      for count in [1..down]
+        valueLevels.pop()
+    if lastLevel <= level
+      valueLevels.push name
+
+    item.value = valueLevels.join('::')
+    lastLevels[level] = item
+    lastLevel = level
+
+  )
+  if tree[0]
+    if !params.data_option
+      params.data_option = {}
+    params.data_option.options = tree
+  params
+
 class Index extends App.ControllerTabs
   requiredPermission: 'admin.object'
   constructor: ->
@@ -135,6 +177,7 @@ class New extends App.ControllerGenericNew
 
   onSubmit: (e) =>
     params = @formParam(e.target)
+    params = treeParams(e, params)
 
     # show attributes for create_middle in two column style
     if params.screens && params.screens.create_middle
@@ -184,6 +227,8 @@ class Edit extends App.ControllerGenericEdit
       #if attribute.name is 'data_type'
       #  attribute.disabled = true
 
+    console.log('configure_attributes', configure_attributes)
+
     @controller = new App.ControllerForm(
       model:
         configure_attributes: configure_attributes
@@ -195,6 +240,7 @@ class Edit extends App.ControllerGenericEdit
 
   onSubmit: (e) =>
     params = @formParam(e.target)
+    params = treeParams(e, params)
 
     # show attributes for create_middle in two column style
     if params.screens && params.screens.create_middle

+ 4 - 4
app/assets/javascripts/app/lib/app_post/_object_organization_autocompletion.coffee

@@ -390,14 +390,14 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
       properties:
         translateX: 0
       options:
-        speed: 300
+        duration: 240
 
     # fade out list
     @recipientList.velocity
       properties:
         translateX: '-100%'
       options:
-        speed: 300
+        duration: 240
         complete: => @recipientList.height(@organizationList.height())
 
   hideOrganizationMembers: (e) =>
@@ -413,7 +413,7 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
       properties:
         translateX: 0
       options:
-        speed: 300
+        duration: 240
 
     # reset list height
     @recipientList.height('')
@@ -423,7 +423,7 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
       properties:
         translateX: '100%'
       options:
-        speed: 300
+        duration: 240
         complete: => @organizationList.addClass('hide')
 
   newObject: (e) ->

+ 232 - 41
app/assets/javascripts/app/lib/app_post/searchable_select.coffee

@@ -1,19 +1,25 @@
 class App.SearchableSelect extends Spine.Controller
 
   events:
-    'input .js-input':                  'onInput'
-    'blur .js-input':                   'onBlur'
-    'focus .js-input':                  'onFocus'
-    'click .js-option':                 'selectItem'
-    'mouseenter .js-option':            'highlightItem'
-    'shown.bs.dropdown':                'onDropdownShown'
-    'hidden.bs.dropdown':               'onDropdownHidden'
+    'input .js-input':       'onInput'
+    'blur .js-input':        'onBlur'
+    'focus .js-input':       'onFocus'
+    'click .js-option':      'selectItem'
+    'click .js-enter':       'navigateIn'
+    'click .js-back':        'navigateOut'
+    'mouseenter .js-option': 'highlightItem'
+    'mouseenter .js-enter':  'highlightItem'
+    'mouseenter .js-back':   'highlightItem'
+    'shown.bs.dropdown':     'onDropdownShown'
+    'hidden.bs.dropdown':    'onDropdownHidden'
 
   elements:
-    '.js-option': 'option_items'
+    '.js-dropdown': 'dropdown'
+    '.js-option, .js-enter': 'optionItems'
     '.js-input': 'input'
     '.js-shadow': 'shadowInput'
     '.js-optionsList': 'optionsList'
+    '.js-optionsSubmenu': 'optionsSubmenu'
     '.js-autocomplete-invisible': 'invisiblePart'
     '.js-autocomplete-visible': 'visiblePart'
 
@@ -27,32 +33,95 @@ class App.SearchableSelect extends Spine.Controller
     @render()
 
   render: ->
-    firstSelected = _.find @options.attribute.options, (option) -> option.selected
+    firstSelected = _.find @attribute.options, (option) -> option.selected
 
     if firstSelected
-      @options.attribute.valueName = firstSelected.name
-      @options.attribute.value = firstSelected.value
-    else if @options.attribute.unknown && @options.attribute.value
-      @options.attribute.valueName = @options.attribute.value
-
-    @options.attribute.renderedOptions = App.view('generic/searchable_select_options')
-      options: @options.attribute.options
-
-    @html App.view('generic/searchable_select')( @options.attribute )
-
-    @input.on 'keydown', @navigate
+      @attribute.valueName = firstSelected.name
+      @attribute.value = firstSelected.value
+    else if @attribute.unknown && @attribute.value
+      @attribute.valueName = @attribute.value
+    else if @hasSubmenu @attribute.options
+      @attribute.valueName = @getName @attribute.value, @attribute.options
+
+    @html App.view('generic/searchable_select')
+      attribute: @attribute
+      options: @renderAllOptions '', @attribute.options, 0
+      submenus: @renderSubmenus @attribute.options
+
+    # initial data
+    @currentMenu = @findMenuContainingValue @attribute.value
+    @level = @getIndex @currentMenu
+
+  renderSubmenus: (options) ->
+    html = ''
+    if options
+      for option in options
+        if option.children
+          html += App.view('generic/searchable_select_submenu')
+            options: @renderOptions(option.children)
+            parentValue: option.value
+            title: option.name
+
+          if @hasSubmenu(option.children)
+            html += @renderSubmenus option.children
+    html
+
+  hasSubmenu: (options) ->
+    return false if !options
+    for option in options
+      return true if option.children
+    return false
+
+  getName: (value, options) ->
+    for option in options
+      if option.value is value
+        return option.name
+      if option.children
+        name = @getName value, option.children
+        return name if name isnt undefined
+    undefined
+
+  renderOptions: (options) ->
+    html = ''
+    for option in options
+      html += App.view('generic/searchable_select_option')
+        option: option
+        class: if option.children then 'js-enter' else 'js-option'
+    html
+
+  renderAllOptions: (parentName, options, level) ->
+    html = ''
+    if options
+      for option in options
+        className = if option.children then 'js-enter' else 'js-option'
+        if level && level > 0
+          className += ' is-hidden is-child'
+
+        html += App.view('generic/searchable_select_option')
+          option: option
+          class: className
+          detail: parentName
+
+        if option.children
+          html += @renderAllOptions "#{parentName} — #{option.name}", option.children, level+1
+    html
 
   onDropdownShown: =>
     @input.on 'click', @stopPropagation
     @highlightFirst()
+    $(document).on 'keydown.searchable_select', @navigate
+    if @level > 0
+      @showSubmenu(@currentMenu)
     @isOpen = true
 
   onDropdownHidden: =>
     @input.off 'click', @stopPropagation
-    @option_items.removeClass '.is-active'
+    @unhighlightCurrentItem()
+    $(document).off 'keydown.searchable_select'
     @isOpen = false
 
   toggle: =>
+    @currentItem = null
     @$('[data-toggle="dropdown"]').dropdown('toggle')
 
   stopPropagation: (event) ->
@@ -62,8 +131,8 @@ class App.SearchableSelect extends Spine.Controller
     switch event.keyCode
       when 40 then @nudge event, 1 # down
       when 38 then @nudge event, -1 # up
-      when 39 then @fillWithAutocompleteSuggestion event # right
-      when 37 then @fillWithAutocompleteSuggestion event # left
+      when 39 then @autocompleteOrNavigateIn event # right
+      when 37 then @autocompleteOrNavigateOut event # left
       when 13 then @onEnter event
       when 27 then @onEscape()
       when 9 then @onTab event
@@ -71,12 +140,20 @@ class App.SearchableSelect extends Spine.Controller
   onEscape: ->
     @toggle() if @isOpen
 
+  getCurrentOptions: ->
+    @currentMenu.find('.js-option, .js-enter, .js-back')
+
+  getOptionIndex: (menu, value) ->
+    menu.find('.js-option, .js-enter').filter("[data-value=\"#{value}\"]").index()
+
   nudge: (event, direction) ->
     return @toggle() if not @isOpen
 
+    options = @getCurrentOptions()
+
     event.preventDefault()
-    visibleOptions = @option_items.not('.is-hidden')
-    highlightedItem = @option_items.filter('.is-active')
+    visibleOptions = options.not('.is-hidden')
+    highlightedItem = options.filter('.is-active')
     currentPosition = visibleOptions.index(highlightedItem)
 
     currentPosition += direction
@@ -84,10 +161,24 @@ class App.SearchableSelect extends Spine.Controller
     return if currentPosition < 0
     return if currentPosition > visibleOptions.size() - 1
 
-    @option_items.removeClass('is-active')
-    visibleOptions.eq(currentPosition).addClass('is-active')
+    @unhighlightCurrentItem()
+    @currentItem = visibleOptions.eq(currentPosition)
+    @currentItem.addClass('is-active')
     @clearAutocomplete()
 
+  autocompleteOrNavigateIn: (event) ->
+    if @currentItem.hasClass('js-enter')
+      @navigateIn(event)
+    else
+      @fillWithAutocompleteSuggestion(event)
+
+  autocompleteOrNavigateOut: (event) ->
+    # if we're in a depth then navigateOut
+    if @level != 0
+      @navigateOut(event)
+    else
+      @fillWithAutocompleteSuggestion(event)
+
   fillWithAutocompleteSuggestion: (event) ->
     if !@suggestion
       return
@@ -129,11 +220,96 @@ class App.SearchableSelect extends Spine.Controller
     @shadowInput.val event.currentTarget.getAttribute('data-value')
     @shadowInput.trigger('change')
 
+  navigateIn: (event) ->
+    event.stopPropagation()
+    @navigateDepth(1)
+
+  navigateOut: (event) ->
+    event.stopPropagation()
+    @navigateDepth(-1)
+
+  navigateDepth: (dir) ->
+    return if @animating
+    if dir > 0
+      target = @currentItem.attr('data-value')
+      target_menu = @optionsSubmenu.filter("[data-parent-value=\"#{target}\"]")
+    else
+      target_menu = @findMenuContainingValue @currentMenu.attr('data-parent-value')
+
+    @animateToSubmenu(target_menu, dir)
+
+    @level+=dir
+
+  animateToSubmenu: (target_menu, direction) ->
+    @animating = true
+    target_menu.prop('hidden', false)
+    @dropdown.height(Math.max(target_menu.height(), @currentMenu.height()))
+    oldCurrentItem = @currentItem
+
+    @currentMenu.data('current_item_index', @currentItem.index())
+    # default: 1 (first item after the back button)
+    target_item_index = target_menu.data('current_item_index') || 1
+    # if the direction is out then we know the target item -> its the parent item
+    if direction is -1
+      value = @currentMenu.attr('data-parent-value')
+      target_item_index = @getOptionIndex(target_menu, value)
+
+    @currentItem = target_menu.children().eq(target_item_index)
+    @currentItem.addClass('is-active')
+
+    target_menu.velocity
+      properties:
+        translateX: [0, direction*100+'%']
+      options:
+        duration: 240
+
+    @currentMenu.velocity
+      properties:
+        translateX: [direction*-100+'%', 0]
+      options:
+        duration: 240
+        complete: =>
+          oldCurrentItem.removeClass('is-active')
+          $.Velocity.hook(@currentMenu, 'translateX', '')
+          @currentMenu.prop('hidden', true)
+          @dropdown.height(target_menu.height())
+          @currentMenu = target_menu
+          @animating = false
+
+  showSubmenu: (menu) ->
+    @currentMenu.prop('hidden', true)
+    menu.prop('hidden', false)
+    @dropdown.height(menu.height())
+
+  findMenuContainingValue: (value) ->
+    return @optionsList if !value
+
+    # in case of numbers
+    if !value.split && value.toString
+      value = value.toString()
+    path = value.split('::')
+    if path.length == 1
+      return @optionsList
+    else
+      path.pop()
+      return @optionsSubmenu.filter("[data-parent-value=\"#{path.join('::')}\"]")
+
+  getIndex: (menu) ->
+    parentValue = menu.attr('data-parent-value')
+    return 0 if !parentValue
+    return parentValue.split('::').length
+
   onTab: (event) ->
     return if not @isOpen
     event.preventDefault()
 
   onEnter: (event) ->
+    if @currentItem
+      if @currentItem.hasClass('js-enter')
+        return @navigateIn(event)
+      else if @currentItem.hasClass('js-back')
+        return @navigateOut(event)
+
     @clearAutocomplete()
 
     if not @isOpen
@@ -144,13 +320,14 @@ class App.SearchableSelect extends Spine.Controller
 
     event.preventDefault()
 
-    selected = @option_items.filter('.is-active')
-    if selected.length || !@options.attribute.unknown
-      valueName = selected.text().trim()
-      value     = selected.attr('data-value')
+    if @currentItem || !@attribute.unknown
+      valueName = @currentItem.text().trim()
+      value     = @currentItem.attr('data-value')
       @input.val valueName
       @shadowInput.val value
 
+    @currentItem = null
+
     @input.trigger('change')
     @shadowInput.trigger('change')
     @toggle()
@@ -169,32 +346,46 @@ class App.SearchableSelect extends Spine.Controller
     @query = @input.val()
     @filterByQuery @query
 
-    if @options.attribute.unknown
+    if @attribute.unknown
       @shadowInput.val @query
 
   filterByQuery: (query) ->
     query = escapeRegExp(query)
     regex = new RegExp(query.split(' ').join('.*'), 'i')
 
-    @option_items
+    @optionsList.addClass 'is-filtered'
+
+    @optionItems
       .addClass 'is-hidden'
       .filter ->
         @textContent.match(regex)
       .removeClass 'is-hidden'
 
-    if @options.attribute.unknown && @option_items.length == @option_items.filter('.is-hidden').length
-      @option_items.removeClass 'is-hidden'
-      @option_items.removeClass 'is-active'
+    if !query
+      @optionItems.filter('.is-child').addClass 'is-hidden'
+
+    # if all are hidden
+    if @attribute.unknown && @optionItems.length == @optionItems.filter('.is-hidden').length
+      @optionItems.not('.is-child').removeClass 'is-hidden'
+      @unhighlightCurrentItem()
+      @optionsList.removeClass 'is-filtered'
     else
       @highlightFirst(true)
 
   highlightFirst: (autocomplete) ->
-    first = @option_items.removeClass('is-active').not('.is-hidden').first()
-    first.addClass 'is-active'
+    @unhighlightCurrentItem()
+    @currentItem = @getCurrentOptions().not('.is-hidden').first()
+    @currentItem.addClass 'is-active'
 
     if autocomplete
-      @autocomplete first.attr('data-value'), first.text().trim()
+      @autocomplete @currentItem.attr('data-value'), @currentItem.text().trim()
 
   highlightItem: (event) =>
-    @option_items.removeClass('is-active')
-    $(event.currentTarget).addClass('is-active')
+    @unhighlightCurrentItem()
+    @currentItem = $(event.currentTarget)
+    @currentItem.addClass('is-active')
+
+  unhighlightCurrentItem: ->
+    return if !@currentItem
+    @currentItem.removeClass('is-active')
+    @currentItem = null

+ 1 - 2
app/assets/javascripts/app/lib/app_post/z_searchable_ajax_select.coffee

@@ -70,8 +70,7 @@ class App.SearchableAjaxSelect extends App.SearchableSelect
         options.push data
 
     # fill template with gathered options
-    @optionsList.html App.view('generic/searchable_select_options')
-      options: options
+    @optionsList.html @renderOptions options
 
     # refresh elements
     @refreshElements()

+ 16 - 13
app/assets/javascripts/app/views/generic/searchable_select.jst.eco

@@ -1,26 +1,29 @@
 <div class="dropdown-toggle" data-toggle="dropdown">
   <input
     class="searchableSelect-shadow form-control js-shadow"
-    id="<%= @id %>"
-    name="<%= @name %>"
-    <%= @required %>
-    <%= @autofocus %>
-    value="<%= @value %>"
+    id="<%= @attribute.id %>"
+    name="<%= @attribute.name %>"
+    <%= @attribute.required %>
+    <%= @attribute.autofocus %>
+    value="<%= @attribute.value %>"
   >
   <input
-    class="searchableSelect-main form-control js-input<%= " #{ @class }" if @class %>"
-    placeholder="<%= @placeholder %>"
-    value="<%= @valueName %>"
+    class="searchableSelect-main form-control js-input<%= " #{ @attribute.class }" if @attribute.class %>"
+    placeholder="<%= @attribute.placeholder %>"
+    value="<%= @attribute.valueName %>"
     autocomplete="off"
-    <%= @required %>
+    <%= @attribute.required %>
    >
   <div class="searchableSelect-autocomplete">
     <span class="searchableSelect-autocomplete-invisible js-autocomplete-invisible"></span>
     <span class="searchableSelect-autocomplete-visible js-autocomplete-visible"></span>
   </div>
-  <% if !@ajax: %><%- @Icon('arrow-down', 'dropdown-arrow') %><% end %>
+  <% if !@attribute.ajax: %><%- @Icon('arrow-down', 'dropdown-arrow') %><% end %>
   <div class="small loading icon"></div>
 </div>
-<ul class="dropdown-menu dropdown-menu-left js-optionsList" role="menu">
-  <%- @renderedOptions %>
-</ul>
+<div class="dropdown-menu dropdown-menu-left dropdown-menu--has-submenu js-dropdown">
+  <ul class="js-optionsList" role="menu">
+    <%- @options %>
+  </ul>
+  <%- @submenus %>
+</div>

+ 8 - 0
app/assets/javascripts/app/views/generic/searchable_select_option.jst.eco

@@ -0,0 +1,8 @@
+<li role="presentation" class="<%= @class %>" data-value="<%= @option.value %>" title="<%= @option.name %><% if @detail: %><%= @detail %><% end %>">
+  <span class="searchableSelect-option-text">
+    <%= @option.name %><% if @detail: %><span class="dropdown-detail"><%= @detail %></span><% end %>
+  </span>
+  <% if @option.children: %>
+    <%- @Icon('arrow-right', 'recipientList-arrow') %>
+  <% end %>
+</li>

+ 0 - 5
app/assets/javascripts/app/views/generic/searchable_select_options.jst.eco

@@ -1,5 +0,0 @@
-<% if @options: %>
-  <% for option in @options: %>
-    <li role="presentation" class="js-option" data-value="<%= option.value %>"><%= option.name %>
-  <% end %>
-<% end %>

Some files were not shown because too many files changed in this diff