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:
Cameron Sutter 2013-09-03 13:01:49 -06:00
parent edd4625b63
commit 0186ae5847
9 changed files with 242 additions and 53 deletions

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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, "\\$&")

View File

@ -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}}"
>

View File

@ -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>

View File

@ -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())

View File

@ -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