search box on assignments index page
fixes CNVS-7191 test plan: - type a search term into the search box - assignment groups without a matching assignment should disappear - assignments that do not match should disappear - assignment groups that were collapsed should expand if there are matching assignments and then collapse when the search box is empty Change-Id: Ibecfd35bc74403dd97bee928eb3be427f6cc554a Reviewed-on: https://gerrit.instructure.com/24120 Reviewed-by: Simon Williams <simon@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Amber Taniuchi <amber@instructure.com> Product-Review: Cameron Sutter <csutter@instructure.com>
This commit is contained in:
parent
edd4625b63
commit
0186ae5847
|
@ -18,15 +18,14 @@
|
|||
require [
|
||||
'compiled/collections/AssignmentGroupCollection'
|
||||
'compiled/models/Course'
|
||||
'compiled/views/InputFilterView'
|
||||
'compiled/views/assignments/AssignmentGroupListView'
|
||||
'compiled/views/assignments/CreateGroupView'
|
||||
'compiled/views/assignments/IndexView'
|
||||
'compiled/views/assignments/AssignmentSettingsView'
|
||||
'compiled/views/assignments/AssignmentGroupWeightsView'
|
||||
'compiled/views/assignments/ToggleShowByView'
|
||||
], (AssignmentGroupCollection, Course, InputFilterView,
|
||||
AssignmentGroupListView, CreateGroupView, IndexView, AssignmentSettingsView,
|
||||
], (AssignmentGroupCollection, Course, AssignmentGroupListView,
|
||||
CreateGroupView, IndexView, AssignmentSettingsView,
|
||||
AssignmentGroupWeightsView, ToggleShowByView) ->
|
||||
|
||||
course = new Course
|
||||
|
@ -42,9 +41,6 @@ require [
|
|||
include: includes
|
||||
override_assignment_dates: !ENV.PERMISSIONS.manage
|
||||
|
||||
inputFilterView = new InputFilterView
|
||||
collection: assignmentGroups
|
||||
|
||||
assignmentGroupsView = new AssignmentGroupListView
|
||||
collection: assignmentGroups
|
||||
sortURL: ENV.URLS.sort_url
|
||||
|
@ -71,10 +67,10 @@ require [
|
|||
|
||||
@app = new IndexView
|
||||
assignmentGroupsView: assignmentGroupsView
|
||||
inputFilterView: inputFilterView
|
||||
assignmentSettingsView: assignmentSettingsView
|
||||
createGroupView: createGroupView
|
||||
showByView: showByView
|
||||
collection: assignmentGroups
|
||||
|
||||
@app.render()
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ define [
|
|||
# this should eventually happen at a higher level (eg for all views), but
|
||||
# we need to make sure that all children view are also children dom
|
||||
# elements first.
|
||||
render: ->
|
||||
render: =>
|
||||
@createAssignmentView.remove() if @createAssignmentView
|
||||
@editGroupView.remove() if @editGroupView
|
||||
@deleteGroupView.remove() if @deleteGroupView
|
||||
|
@ -91,7 +91,7 @@ define [
|
|||
assign.doNotParse() if assign.multipleDueDates()
|
||||
|
||||
@collection = @model.get('assignments')
|
||||
@collection.on 'add', @expand
|
||||
@collection.on 'add', => @expand(false)
|
||||
|
||||
initializeChildViews: ->
|
||||
@editGroupView = false
|
||||
|
@ -162,25 +162,70 @@ define [
|
|||
|
||||
results
|
||||
|
||||
isExpanded: ->
|
||||
search: (regex) ->
|
||||
atleastone = false
|
||||
@collection.each (as) =>
|
||||
atleastone = true if as.assignmentView.search(regex)
|
||||
if atleastone
|
||||
@show()
|
||||
@expand(false)
|
||||
else
|
||||
@hide()
|
||||
atleastone
|
||||
|
||||
endSearch: ->
|
||||
@show()
|
||||
@collapseIfNeeded()
|
||||
@resetNoToggleCache()
|
||||
@collection.each (as) =>
|
||||
as.assignmentView.endSearch()
|
||||
|
||||
shouldBeExpanded: ->
|
||||
@cache.get(@cacheKey())
|
||||
|
||||
expand: =>
|
||||
@toggle(true) if !@isExpanded()
|
||||
collapseIfNeeded: ->
|
||||
@collapse(false) unless @shouldBeExpanded()
|
||||
|
||||
toggle: (setTo=false) ->
|
||||
expand: (toggleCache=true) =>
|
||||
@_setNoToggleCache() unless toggleCache
|
||||
@toggleCollapse() unless @currentlyExpanded()
|
||||
|
||||
collapse: (toggleCache=true) =>
|
||||
@_setNoToggleCache() unless toggleCache
|
||||
@toggleCollapse() if @currentlyExpanded()
|
||||
|
||||
toggleCollapse: (toggleCache=true) ->
|
||||
@_setNoToggleCache() unless toggleCache
|
||||
@$el.find('.element_toggler').click()
|
||||
@cache.set(@cacheKey(), setTo)
|
||||
|
||||
_setNoToggleCache: ->
|
||||
@$el.find('.element_toggler').data("noToggleCache", true)
|
||||
|
||||
currentlyExpanded: ->
|
||||
# the 2 states of the element toggler are true and "false"
|
||||
if @$el.find('.element_toggler').attr("aria-expanded") == "false"
|
||||
false
|
||||
else
|
||||
true
|
||||
|
||||
cacheKey: ->
|
||||
["course", @course.get('id'), "user", @currentUserId(), "ag", @model.get('id'), "expanded"]
|
||||
|
||||
toggleArrow: (ev) ->
|
||||
toggleArrow: (ev) =>
|
||||
arrow = $(ev.currentTarget).children('i')
|
||||
arrow.toggleClass('icon-mini-arrow-down').toggleClass('icon-mini-arrow-right')
|
||||
@toggleExpanded()
|
||||
@toggleCache() unless $(ev.currentTarget).data("noToggleCache")
|
||||
#reset noToggleCache because it is a one-time-use-only flag
|
||||
@resetNoToggleCache(ev.currentTarget)
|
||||
|
||||
toggleExpanded: ->
|
||||
resetNoToggleCache: (selector=null) ->
|
||||
if selector?
|
||||
obj = $(selector)
|
||||
else
|
||||
obj = @$el.find('.element_toggler')
|
||||
obj.data("noToggleCache", false)
|
||||
|
||||
toggleCache: ->
|
||||
key = @cacheKey()
|
||||
expanded = !@cache.get(key)
|
||||
@cache.set(key, expanded)
|
||||
|
|
|
@ -18,12 +18,11 @@
|
|||
define [
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'compiled/class/cache'
|
||||
'compiled/views/SortableCollectionView'
|
||||
'compiled/views/assignments/AssignmentGroupListItemView'
|
||||
'jst/assignments/AssignmentGroupList'
|
||||
'jst/assignments/NoAssignmentsListItem'
|
||||
], (_, Backbone, Cache, SortableCollectionView, AssignmentGroupListItemView, template, NoAssignmentsListItem) ->
|
||||
], (_, Backbone, SortableCollectionView, AssignmentGroupListItemView, template, NoAssignmentsListItem) ->
|
||||
|
||||
class AssignmentGroupListView extends SortableCollectionView
|
||||
@optionProperty 'course'
|
||||
|
@ -33,18 +32,16 @@ define [
|
|||
|
||||
@optionProperty 'assignment_sort_base_url'
|
||||
|
||||
initialize: ->
|
||||
attachCollection: ->
|
||||
super
|
||||
$.extend true, this, Cache
|
||||
@itemViewOptions = course: @course
|
||||
|
||||
render: ->
|
||||
render: =>
|
||||
super(ENV.PERMISSIONS.manage)
|
||||
|
||||
renderItem: (model) ->
|
||||
renderItem: (model) =>
|
||||
view = super
|
||||
unless model.groupView.isExpanded()
|
||||
model.groupView.toggle()
|
||||
model.groupView.collapseIfNeeded()
|
||||
view
|
||||
|
||||
createItemView: (model) ->
|
||||
|
@ -70,14 +67,6 @@ define [
|
|||
firstResetLanded: not @empty
|
||||
)
|
||||
|
||||
# This will be used when we implement searching
|
||||
expandAll: ->
|
||||
for m in @collection.models
|
||||
if !m.groupView.isExpanded()
|
||||
# force expand it
|
||||
# but it will retain its state in cache
|
||||
m.groupView.toggle()
|
||||
|
||||
_initSort: ->
|
||||
super
|
||||
@$list.on('sortstart', @collapse)
|
||||
|
|
|
@ -33,6 +33,9 @@ define [
|
|||
super
|
||||
@initializeChildViews()
|
||||
|
||||
# we need the following line in order to access this view later
|
||||
@model.assignmentView = @
|
||||
|
||||
if @canManage()
|
||||
@model.on('change:published', @updatePublishState)
|
||||
|
||||
|
@ -77,14 +80,15 @@ define [
|
|||
|
||||
createModuleToolTip: =>
|
||||
link = @$el.find('.tooltip_link')
|
||||
link.tooltip
|
||||
position:
|
||||
my: 'center bottom'
|
||||
at: 'center top-10'
|
||||
collision: 'fit fit'
|
||||
tooltipClass: 'center bottom vertical'
|
||||
content: ->
|
||||
$(link.data('tooltipSelector')).html()
|
||||
if link.length > 0
|
||||
link.tooltip
|
||||
position:
|
||||
my: 'center bottom'
|
||||
at: 'center top-10'
|
||||
collision: 'fit fit'
|
||||
tooltipClass: 'center bottom vertical'
|
||||
content: ->
|
||||
$(link.data('tooltipSelector')).html()
|
||||
|
||||
toJSON: ->
|
||||
data = @model.toView()
|
||||
|
@ -117,3 +121,14 @@ define [
|
|||
|
||||
canManage: ->
|
||||
ENV.PERMISSIONS.manage
|
||||
|
||||
search: (regex) ->
|
||||
if @model.get('name').match(regex)
|
||||
@show()
|
||||
return true
|
||||
else
|
||||
@hide()
|
||||
return false
|
||||
|
||||
endSearch: (regex) ->
|
||||
@show()
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
define [
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'jst/assignments/IndexView'
|
||||
], (Backbone, template) ->
|
||||
'jst/assignments/NoAssignmentsSearch'
|
||||
], (_, Backbone, template, NoAssignments) ->
|
||||
|
||||
class IndexView extends Backbone.View
|
||||
|
||||
|
@ -9,11 +11,13 @@ define [
|
|||
el: '#content'
|
||||
|
||||
@child 'assignmentGroupsView', '[data-view=assignmentGroups]'
|
||||
@child 'inputFilterView', '[data-view=inputFilter]'
|
||||
@child 'createGroupView', '[data-view=createGroup]'
|
||||
@child 'assignmentSettingsView', '[data-view=assignmentSettings]'
|
||||
@child 'showByView', '[data-view=showBy]'
|
||||
|
||||
events:
|
||||
'keyup #search_term': 'search'
|
||||
|
||||
els:
|
||||
'#addGroup': '$addGroupButton'
|
||||
'#assignmentSettingsCog': '$assignmentSettingsButton'
|
||||
|
@ -28,3 +32,43 @@ define [
|
|||
if @assignmentSettingsView
|
||||
@assignmentSettingsView.hide()
|
||||
@assignmentSettingsView.setTrigger @$assignmentSettingsButton
|
||||
|
||||
search: _.debounce ->
|
||||
@filterResults()
|
||||
, 200
|
||||
|
||||
filterResults: =>
|
||||
term = $('#search_term').val()
|
||||
if term == ""
|
||||
#show all
|
||||
@collection.each (group) =>
|
||||
group.groupView.endSearch()
|
||||
|
||||
#remove noAssignments placeholder
|
||||
if @noAssignments?
|
||||
@noAssignments.remove()
|
||||
@noAssignments = null
|
||||
else
|
||||
regex = new RegExp(@cleanSearchTerm(term), 'ig')
|
||||
#search
|
||||
atleastoneGroup = false
|
||||
@collection.each (group) =>
|
||||
atleastoneGroup = true if group.groupView.search(regex)
|
||||
|
||||
#add noAssignments placeholder
|
||||
if !atleastoneGroup
|
||||
unless @noAssignments
|
||||
@noAssignments = new Backbone.View
|
||||
template: NoAssignments
|
||||
tagName: "li"
|
||||
className: "item-group-condensed"
|
||||
ul = @assignmentGroupsView.$el.children(".collectionViewItems")
|
||||
ul.append(@noAssignments.render().el)
|
||||
else
|
||||
#remove noAssignments placeholder
|
||||
if @noAssignments?
|
||||
@noAssignments.remove()
|
||||
@noAssignments = null
|
||||
|
||||
cleanSearchTerm: (text) ->
|
||||
text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
|
|
@ -9,7 +9,6 @@
|
|||
name="search_term"
|
||||
type="search"
|
||||
value=""
|
||||
data-view="inputFilter"
|
||||
placeholder="{{#t "search_for_assignment"}}Search for Assignment{{/t}}"
|
||||
aria-label="{{#t "search_for_assignment"}}Search for Assignment{{/t}}"
|
||||
>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<div>
|
||||
<div class="ig-header">
|
||||
<h2 class="ig-header-title" aria-label="{{#t "aria_assignments"}}Assignments{{/t}}">
|
||||
<i class="icon-mini-arrow-down"></i>
|
||||
{{#t "assignments"}}Assignments{{/t}}
|
||||
</h2>
|
||||
</div>
|
||||
<ul class="ig-list">
|
||||
<li>
|
||||
<div class="ig-row ig-row-empty">
|
||||
<div class="ig-empty-msg">
|
||||
{{#t "no_assignments_found"}}No assignments found{{/t}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
|
@ -7,6 +7,7 @@ define [
|
|||
'compiled/views/assignments/AssignmentListItemView'
|
||||
'jquery'
|
||||
'helpers/jquery.simulate'
|
||||
'compiled/behaviors/elementToggler'
|
||||
], (Backbone, AssignmentGroupCollection, AssignmentGroup, Assignment, AssignmentGroupListItemView, AssignmentListItemView, $) ->
|
||||
|
||||
fixtures = $('#fixtures')
|
||||
|
@ -160,20 +161,32 @@ define [
|
|||
json = view.toJSON()
|
||||
equal json.groupWeight, 1
|
||||
|
||||
test "isExpanded returnes expanded state", ->
|
||||
test "shouldBeExpanded returnes cache state", ->
|
||||
view = createView(@model)
|
||||
view.expand()
|
||||
ok view.isExpanded()
|
||||
#make sure the cache starts at true
|
||||
view.toggleCache() unless view.shouldBeExpanded()
|
||||
|
||||
test "toggle toggles expansion", ->
|
||||
ok view.shouldBeExpanded()
|
||||
|
||||
view.toggleCache()
|
||||
ok !view.shouldBeExpanded()
|
||||
|
||||
test "currentlyExpanded returns expanded state", ->
|
||||
view = createView(@model)
|
||||
view.expand()
|
||||
#make sure the cache starts at true
|
||||
view.toggleCache() unless view.shouldBeExpanded()
|
||||
ok view.currentlyExpanded()
|
||||
|
||||
view.toggle(false)
|
||||
ok !view.isExpanded()
|
||||
test "toggleCollapse toggles expansion", ->
|
||||
view = createView(@model)
|
||||
#make sure the cache starts at true
|
||||
view.toggleCache() unless view.shouldBeExpanded()
|
||||
|
||||
view.toggle(true)
|
||||
ok view.isExpanded()
|
||||
view.toggleCollapse()
|
||||
ok !view.currentlyExpanded()
|
||||
|
||||
view.toggleCollapse()
|
||||
ok view.currentlyExpanded()
|
||||
|
||||
test "displayableRules", ->
|
||||
model = createAssignmentGroup(group2())
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
define [
|
||||
'Backbone'
|
||||
'compiled/models/AssignmentGroup'
|
||||
'compiled/models/Assignment'
|
||||
'compiled/models/Course'
|
||||
'compiled/collections/AssignmentGroupCollection'
|
||||
'compiled/views/assignments/AssignmentGroupListView'
|
||||
'compiled/views/assignments/IndexView'
|
||||
'jquery'
|
||||
'helpers/jquery.simulate'
|
||||
], (Backbone, AssignmentGroup, Assignment, Course, AssignmentGroupCollection, AssignmentGroupListView, IndexView, $) ->
|
||||
|
||||
|
||||
fixtures = $('#fixtures')
|
||||
|
||||
assignmentIndex = () ->
|
||||
$('<div id="content"></div>').appendTo fixtures
|
||||
|
||||
course = new Course {id: 1}
|
||||
|
||||
group1 = new AssignmentGroup
|
||||
name: "Group 1"
|
||||
assignments: [{id: 1, name: 'Foo Name'}, {id: 2, name: 'Bar Title'}]
|
||||
group2 = new AssignmentGroup
|
||||
name: "Group 2"
|
||||
assignments: [{id: 1, name: 'Baz Title'}, {id: 2, name: 'Qux Name'}]
|
||||
assignmentGroups = new AssignmentGroupCollection [group1, group2],
|
||||
course: course
|
||||
|
||||
assignmentGroupsView = new AssignmentGroupListView
|
||||
collection: assignmentGroups
|
||||
course: course
|
||||
|
||||
app = new IndexView
|
||||
assignmentGroupsView: assignmentGroupsView
|
||||
collection: assignmentGroups
|
||||
createGroupView: false
|
||||
assignmentSettingsView: false
|
||||
showByView: false
|
||||
|
||||
app.render()
|
||||
|
||||
oldENV = null
|
||||
|
||||
module 'assignmentIndex',
|
||||
setup: ->
|
||||
oldENV = window.ENV
|
||||
window.ENV =
|
||||
MODULES: {}
|
||||
PERMISSIONS:
|
||||
manage: true
|
||||
|
||||
teardown: ->
|
||||
window.ENV = oldENV
|
||||
|
||||
test 'should filter by search term', ->
|
||||
|
||||
view = assignmentIndex()
|
||||
$('#search_term').val('foo')
|
||||
view.filterResults()
|
||||
equal view.$el.find('.assignment:visible').length, 1
|
||||
|
||||
view = assignmentIndex()
|
||||
$('#search_term').val('BooBerry')
|
||||
view.filterResults()
|
||||
equal view.$el.find('.assignment:visible').length, 0
|
||||
|
||||
view = assignmentIndex()
|
||||
$('#search_term').val('name')
|
||||
view.filterResults()
|
||||
equal view.$el.find('.assignment:visible').length, 2
|
Loading…
Reference in New Issue