diff --git a/ruby/lib/jam_ruby/models/band_search.rb b/ruby/lib/jam_ruby/models/band_search.rb index ced7ea732..0dae6a088 100644 --- a/ruby/lib/jam_ruby/models/band_search.rb +++ b/ruby/lib/jam_ruby/models/band_search.rb @@ -1,12 +1,16 @@ module JamRuby class BandSearch < BaseSearch + cattr_accessor :jschema, :search_meta attr_accessor :user_counters KEY_BAND_SEARCH_TYPE = 'band_search_type' KEY_BAND_TYPE = 'band_type' KEY_PLAY_COMMIT = 'play_commit' KEY_TOUR_OPTION = 'tour_option' + KEY_PERF_SAMPLES = 'perform_samples' + KEY_HIRE_MAX_COST = 'max_cost' + KEY_HIRE_FREE = 'free_gigs' BAND_SEARCH_TYPE_VALS = %W{ to_join to_hire } BAND_SEARCH_TYPES = { @@ -20,6 +24,13 @@ module JamRuby SORT_VALS[1] => 'Latency to Me', } + HIRE_SORT_VALS = %W{ distance price_asc price_desc } + HIRE_SORT_ORDERS = { + HIRE_SORT_VALS[0] => 'Distance to Me', + HIRE_SORT_VALS[1] => 'Gig Minimum Price (Low to High)', + HIRE_SORT_VALS[2] => 'Gig Minimum Price (High to Low)', + } + BAND_TYPE_VALS = [ANY_VAL_STR, GenrePlayer::VIRTUAL_BAND, GenrePlayer::TRADITIONAL_BAND, @@ -52,19 +63,37 @@ module JamRuby TOUR_OPTION_VALS[1] => 'No', } - JSON_SCHEMA = BaseSearch::JSON_SCHEMA.merge({ - KEY_BAND_SEARCH_TYPE => BAND_SEARCH_TYPES[0], - KEY_BAND_TYPE => BAND_TYPE_VALS[0], - KEY_PLAY_COMMIT => PLAY_COMMIT_VALS[0], - KEY_TOUR_OPTION => TOUR_OPTION_VALS[0], - }) + PERF_SAMPLES_VALS = TOUR_OPTION_VALS.clone + PERF_SAMPLES = TOUR_OPTIONS.clone - SEARCH_FILTER_META = BaseSearch::SEARCH_FILTER_META.merge({ - sort_order: { keys: self::SORT_VALS, map: self::SORT_ORDERS }, - band_type: { keys: BAND_TYPE_VALS, map: BAND_TYPES }, - play_commit: { keys: PLAY_COMMIT_VALS, map: PLAY_COMMITS }, - tour_option: { keys: TOUR_OPTION_VALS, map: TOUR_OPTIONS } - }) + def self.json_schema + return @@jschema if @@jschema + @@jschema = { + BAND_SEARCH_TYPE_VALS[0] => BaseSearch.json_schema.merge({ + KEY_BAND_TYPE => BAND_TYPE_VALS[0], + KEY_PLAY_COMMIT => PLAY_COMMIT_VALS[0], + KEY_TOUR_OPTION => TOUR_OPTION_VALS[0], + }), + BAND_SEARCH_TYPE_VALS[1] => { + KEY_SORT_ORDER => self::HIRE_SORT_VALS[0], + KEY_GENRES => [], + KEY_SKILL => self::SKILL_VALS[0].to_s, + KEY_GIGS => self::GIG_COUNTS[0].to_s, + KEY_PERF_SAMPLES => self::PERF_SAMPLES[0].to_s, + KEY_HIRE_MAX_COST => 0, + KEY_HIRE_FREE => 0, + }, + } + end + + def self.search_filter_meta + return @@search_meta if @@search_meta + @@search_meta = { + BAND_SEARCH_TYPE_VALS[0] => super(self.json_schema[BAND_SEARCH_TYPE_VALS[0]]), + BAND_SEARCH_TYPE_VALS[1] => super(self.json_schema[BAND_SEARCH_TYPE_VALS[1]], + { keys: HIRE_SORT_VALS, map: HIRE_SORT_ORDERS }), + } + end def self.search_target_class User @@ -155,7 +184,7 @@ module JamRuby end def is_blank? - self.data_blob == JSON_SCHEMA + self.data_blob == self.class.json_schema end def description @@ -168,5 +197,39 @@ module JamRuby str end + def reset_filter(subtype, data=nil) + data ||= self.class.json_schema[subtype] + dblob = self.data_blob + dblob[subtype] = data + self.data_blob = dblob + self.save + end + + def reset_search_results(subtype=BAND_SEARCH_TYPE_VALS[0]) + reset_filter(subtype) + search_results_page(subtype) + end + + def self.search_filter_json(user, subtype=BAND_SEARCH_TYPE_VALS[0]) + self.user_search_filter(user).json[subtype] + end + + def search_results_page(subtype=BAND_SEARCH_TYPE_VALS[0], filter=nil, page=1) + if filter + reset_filter(subtype, filter) + else + filter = self.data_blob[subtype] + end + rel = do_search(filter) + + @page_number = [page.to_i, 1].max + rel = rel.paginate(:page => @page_number, :per_page => self.class::PER_PAGE) + + rel = self.search_includes(rel) + @page_count = rel.total_pages + + process_results_page(rel.all) + end + end end diff --git a/ruby/lib/jam_ruby/models/base_search.rb b/ruby/lib/jam_ruby/models/base_search.rb index bcd645c22..8a1672084 100644 --- a/ruby/lib/jam_ruby/models/base_search.rb +++ b/ruby/lib/jam_ruby/models/base_search.rb @@ -43,27 +43,31 @@ module JamRuby 3 => 'Expert', } - JSON_SCHEMA = { - KEY_SORT_ORDER => self::SORT_VALS[0], - KEY_INSTRUMENTS => [], - KEY_GENRES => [], - KEY_SKILL => self::SKILL_VALS[0].to_s, - KEY_GIGS => self::GIG_COUNTS[0].to_s, - } + def self.json_schema + { + KEY_SORT_ORDER => self::SORT_VALS[0], + KEY_INSTRUMENTS => [], + KEY_GENRES => [], + KEY_SKILL => self::SKILL_VALS[0].to_s, + KEY_GIGS => self::GIG_COUNTS[0].to_s, + } + end - JSON_SCHEMA_KEYS = self::JSON_SCHEMA.keys - MULTI_VALUE_KEYS = self::JSON_SCHEMA.collect { |kk,vv| vv.is_a?(Array) ? kk : nil }.compact - SINGLE_VALUE_KEYS = self::JSON_SCHEMA.keys - self::MULTI_VALUE_KEYS - - SEARCH_FILTER_META = { - per_page: self::PER_PAGE, - filter_keys: { - keys: self::JSON_SCHEMA_KEYS, - multi: self::MULTI_VALUE_KEYS, - single: self::SINGLE_VALUE_KEYS, - }, - sort_order: { keys: self::SORT_VALS, map: self::SORT_ORDERS }, - } + def self.search_filter_meta(jschema=nil, sort_order=nil) + jschema ||= self.json_schema + schema_keys = jschema.keys + sort_order ||= { keys: self::SORT_VALS, map: self::SORT_ORDERS } + multi_keys = jschema.collect { |kk,vv| vv.is_a?(Array) ? kk : nil }.compact + { + per_page: self::PER_PAGE, + filter_keys: { + keys: schema_keys, + multi: multi_keys, + single: schema_keys - multi_keys, + }, + sort_order: sort_order + } + end RESULT_FOLLOW = :follows RESULT_FRIEND = :friends @@ -88,7 +92,7 @@ module JamRuby def self.create_search(user) ms = self.new ms.user = user - ms.data_blob = self::JSON_SCHEMA + ms.data_blob = self.json_schema ms.save! ms end @@ -169,7 +173,7 @@ module JamRuby end def reset_filter - self.data_blob = self.class::JSON_SCHEMA + self.data_blob = self.class.json_schema self.save end @@ -183,7 +187,7 @@ module JamRuby end def is_blank? - self.data_blob == self.class::JSON_SCHEMA + self.data_blob == self.class.json_schema end def description diff --git a/ruby/lib/jam_ruby/models/musician_search.rb b/ruby/lib/jam_ruby/models/musician_search.rb index cb6f789a9..8f97d8a43 100644 --- a/ruby/lib/jam_ruby/models/musician_search.rb +++ b/ruby/lib/jam_ruby/models/musician_search.rb @@ -1,6 +1,7 @@ module JamRuby class MusicianSearch < BaseSearch + cattr_accessor :jschema, :search_meta attr_accessor :user_counters KEY_STUDIOS = 'studio_sessions' @@ -47,16 +48,22 @@ module JamRuby INTEREST_VALS[5] => 'Co-Writing' } - JSON_SCHEMA = BaseSearch::JSON_SCHEMA.merge({ - KEY_INTERESTS => INTEREST_VALS[0], - KEY_STUDIOS => STUDIO_COUNTS[0].to_s, - KEY_AGES => [] - }) + def self.json_schema + return @@jschema if @@jschema + @@jschema = BaseSearch.json_schema.merge({ + KEY_INTERESTS => INTEREST_VALS[0], + KEY_STUDIOS => STUDIO_COUNTS[0].to_s, + KEY_AGES => [] + }) + end - SEARCH_FILTER_META = BaseSearch::SEARCH_FILTER_META.merge({ - interests: { keys: INTEREST_VALS, map: INTERESTS }, - ages: { keys: AGE_COUNTS, map: AGES } - }) + def self.search_filter_meta + return @@search_meta if @@search_meta + @@search_meta = super.merge({ + interests: { keys: INTEREST_VALS, map: INTERESTS }, + ages: { keys: AGE_COUNTS, map: AGES } + }) + end def self.search_target_class User @@ -226,7 +233,7 @@ module JamRuby end def is_blank? - self.data_blob == JSON_SCHEMA + self.data_blob == self.class.json_schema end def description diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 8987a9db8..b116aaffb 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -169,6 +169,7 @@ module JamRuby has_many :performance_samples, :class_name => "JamRuby::PerformanceSample", :foreign_key=> 'player_id' has_one :musician_search, :class_name => 'JamRuby::MusicianSearch' + has_one :band_search, :class_name => 'JamRuby::BandSearch' before_save :create_remember_token, :if => :should_validate_password? before_save :stringify_avatar_info , :if => :updating_avatar diff --git a/web/app/assets/javascripts/findBand.js b/web/app/assets/javascripts/findBand.js deleted file mode 100644 index e7c30f315..000000000 --- a/web/app/assets/javascripts/findBand.js +++ /dev/null @@ -1,257 +0,0 @@ -(function(context,$) { - "use strict"; - - context.JK = context.JK || {}; - context.JK.FindBandScreen = function(app) { - - var logger = context.JK.logger; - var bands = {}; - var bandList; - var instrument_logo_map = context.JK.getInstrumentIconMap24(); - var did_show_band_page = false; - var page_num=1, page_count=0; - var helpBubble = context.JK.HelpBubbleHelper; - var $screen = $('#bands-screen'); - var $results = $screen.find('#band-filter-results'); - - function loadBands(queryString) { - // squelch nulls and undefines - queryString = !!queryString ? queryString : ""; - - $.ajax({ - type: "GET", - url: "/api/search.json?" + queryString, - success: afterLoadBands, - error: app.ajaxError - }); - } - - function search() { - did_show_band_page = true; - var queryString = 'srch_b=1&page='+page_num+'&'; - - // order by - var orderby = $('#band_order_by').val(); - if (typeof orderby != 'undefined' && orderby.length > 0) { - queryString += "orderby=" + orderby + '&'; - } - // genre filter - var genre = $('#band_genre').val(); - if (typeof genre != 'undefined' && !(genre === '')) { - queryString += "genre=" + genre + '&'; - } - // distance filter - var query_param = $('#band_query_distance').val(); - if (query_param !== null && query_param.length > 0) { - var matches = query_param.match(/(\d+)/); - if (0 < matches.length) { - var distance = matches[0]; - queryString += "distance=" + distance + '&'; - } - } - loadBands(queryString); - } - - function refreshDisplay() { - clearResults(); - search(); - } - - function afterLoadBands(mList) { - // display the 'no bands' banner if appropriate - var $noBandsFound = $('#bands-none-found'); - bandList = mList; - - if(bandList.length == 0) { - $noBandsFound.show(); - bands = []; - } - else { - $noBandsFound.hide(); - bands = bandList['bands']; - if (!(typeof bands === 'undefined')) { - $('#band-filter-city').text(bandList['city']); - if (0 == page_count) { - page_count = bandList['page_count']; - } - renderBands(); - } - } - } - - function renderBands() { - var ii, len; - var mTemplate = $('#template-find-band-row').html(); - var pTemplate = $('#template-band-player-info').html(); - var aTemplate = $('#template-band-action-btns').html(); - var eTemplate = $('#template-band-edit-btns').html(); - var bVals, bb, renderings=''; - var instr_logos, instr; - var players, playerVals, aPlayer, isMember; - - for (ii=0, len=bands.length; ii < len; ii++) { - bb = bands[ii]; - instr_logos = ''; - players = ''; - playerVals = {}; - isMember = false; - for (var jj=0, ilen=bb['players'].length; jj'; - } - if (!isMember) { - isMember = aPlayer.user_id == context.JK.currentUserId; - } - playerVals = { - user_id: aPlayer.user_id, - player_name: aPlayer.name, - profile_url: '/client#/profile/' + aPlayer.user_id, - avatar_url: context.JK.resolveAvatarUrl(aPlayer.photo_url), - player_instruments: player_instrs - }; - - players += context.JK.fillTemplate(pTemplate, playerVals); - } - - var actionVals, band_actions; - if (isMember) { - actionVals = { - profile_url: "/client#/bandProfile/" + bb.id, - band_edit_url: "/client#/band/setup/" + bb.id + '/step1', - band_member_url: "/client#/band/setup/" + bb.id + '/step2' - }; - band_actions = context.JK.fillTemplate(eTemplate, actionVals); - } else { - actionVals = { - profile_url: "/client#/bandProfile/" + bb.id, - button_follow: bb['is_following'] ? '' : 'button-orange', - button_message: 'button-orange' - }; - band_actions = context.JK.fillTemplate(aTemplate, actionVals); - } - - var bgenres = ''; - for (jj=0, ilen=bb['genres'].length; jj'; - } - - bgenres += '
'; - - bVals = { - avatar_url: context.JK.resolveBandAvatarUrl(bb.photo_url), - profile_url: "/client#/bandProfile/" + bb.id, - band_name: bb.name, - band_location: bb.city + ', ' + bb.state, - genres: bgenres, - instruments: instr_logos, - biography: bb['biography'], - follow_count: bb['follow_count'], - recording_count: bb['recording_count'], - session_count: bb['session_count'], - band_id: bb['id'], - band_player_template: players, - band_action_template: band_actions - }; - - var $rendering = $(context.JK.fillTemplate(mTemplate, bVals)) - - var $offsetParent = $results.closest('.content'); - var data = {entity_type: 'band'}; - - var options = {positions: ['top', 'bottom', 'right', 'left'], offsetParent: $offsetParent}; - context.JK.helpBubble($('.follower-count', $rendering), 'follower-count', data, options); - context.JK.helpBubble($('.recording-count', $rendering), 'recording-count', data, options); - context.JK.helpBubble($('.session-count', $rendering), 'session-count', data, options); - - $results.append($rendering); - } - - $('.search-m-follow').on('click', followBand); - context.JK.bindHoverEvents(); - } - - function beforeShow(data) { - } - - function afterShow(data) { - if (!did_show_band_page) { - refreshDisplay(); - } - } - - function clearResults() { - bands = {}; - $('#band-filter-results').empty(); - page_num = 1; - page_count = 0; - } - - function followBand(evt) { - // if the band is already followed, remove the button-orange class, and prevent - // the link from working - if (0 == $(this).closest('.button-orange').size()) return false; - $(this).click(function(ee) {ee.preventDefault();}); - - evt.stopPropagation(); - var newFollowing = {}; - newFollowing.band_id = $(this).parent().data('band-id'); - var url = "/api/users/" + context.JK.currentUserId + "/followings"; - $.ajax({ - type: "POST", - dataType: "json", - contentType: 'application/json', - url: url, - data: JSON.stringify(newFollowing), - processData: false, - success: function(response) { - // remove the orange look to indicate it's not selectable - // @FIXME -- this will need to be tweaked when we allow unfollowing - $('div[data-band-id='+newFollowing.band_id+'] .search-m-follow').removeClass('button-orange').addClass('button-grey'); - }, - error: app.ajaxError(arguments) - }); - } - - function events() { - $('#band_query_distance').change(refreshDisplay); - $('#band_genre').change(refreshDisplay); - $('#band_order_by').change(refreshDisplay); - - $('#band-filter-results').closest('.content-body-scroller').bind('scroll', function() { - if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) { - if (page_num < page_count) { - page_num += 1; - search(); - } - } - }); - } - - function initialize() { - var screenBindings = { - 'beforeShow': beforeShow, - 'afterShow': afterShow - }; - app.bindScreen('bands', screenBindings); - - events(); - } - - this.initialize = initialize; - this.renderBands = renderBands; - this.afterShow = afterShow; - this.clearResults = clearResults; - - return this; - } -})(window,jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index 6c3cce4f0..901b875b0 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -1639,6 +1639,19 @@ }); } + function getBandSearchFilter(query) { + var qarg = query === undefined ? '' : query; + return $.get("/api/search/bands.json?"+qarg); + } + + function postBandSearchFilter(query) { + return $.ajax({ + type: "POST", + url: "/api/search/bands.json", + data: query + }); + } + function getMount(options) { var id = getId(options); return $.ajax({ @@ -1852,6 +1865,8 @@ this.addRecordingTimeline = addRecordingTimeline; this.getMusicianSearchFilter = getMusicianSearchFilter; this.postMusicianSearchFilter = postMusicianSearchFilter; + this.getBandSearchFilter = getBandSearchFilter; + this.postBandSearchFilter = postBandSearchFilter; this.playJamTrack = playJamTrack; this.createSignupHint = createSignupHint; this.createAlert = createAlert; @@ -1860,4 +1875,4 @@ }; -})(window,jQuery); \ No newline at end of file +})(window,jQuery); diff --git a/web/app/assets/javascripts/musician_search_filter.js.coffee b/web/app/assets/javascripts/member_search_filter.js.coffee similarity index 79% rename from web/app/assets/javascripts/musician_search_filter.js.coffee rename to web/app/assets/javascripts/member_search_filter.js.coffee index 25d08edbc..4df9e8557 100644 --- a/web/app/assets/javascripts/musician_search_filter.js.coffee +++ b/web/app/assets/javascripts/member_search_filter.js.coffee @@ -31,12 +31,6 @@ context.JK.BaseSearchFilter = class BaseSearchFilter this.registerResultsPagination() - @screen.find('#btn-'+@searchType+'-search-builder').on 'click', => - this.showBuilder() - - @screen.find('#btn-'+@searchType+'-search-reset').on 'click', => - this.resetFilter() - afterShow: () => @screen.find('#'+@searchType+'-search-filter-results').show() @screen.find('#'+@searchType+'-search-filter-builder').hide() @@ -50,6 +44,9 @@ context.JK.BaseSearchFilter = class BaseSearchFilter afterHide: () => @resultsListContainer.empty() + searchMetaData: () => + @searchMeta + renderSearchFilter: () => $.when(@restGet()).done (sFilter) => this.loadSearchFilter(sFilter) @@ -69,8 +66,8 @@ context.JK.BaseSearchFilter = class BaseSearchFilter _populateSelectIdentifier: (identifier) => elem = $ '#'+@searchType+'-search-filter-builder select[name='+identifier+']' - struct = @searchMeta[identifier]['map'] - keys = @searchMeta[identifier]['keys'] + struct = this.searchMetaData()[identifier]['map'] + keys = this.searchMetaData()[identifier]['keys'] this._populateSelectWithKeys(struct, @searchFilter[identifier], keys, elem) _populateSelectWithInt: (sourceStruct, selection, element) => @@ -171,13 +168,19 @@ context.JK.BaseSearchFilter = class BaseSearchFilter getUserFilterResults: () => if this.willSearch(true) - @restGet('results=true').done(this.didSearch) + this.doRestGet() + + doRestGet: (query) => + query2 = 'results=true&' + unless (typeof query == "undefined") + query2 += query + @restGet(query2).done(this.didSearch) performSearch: () => if this.willSearch(true) - $.each @searchMeta.filter_keys.single, (index, key) => + $.each this.searchMetaData().filter_keys.single, (index, key) => @searchFilter[key] = this._builderSelectValue(key) - $.each @searchMeta.filter_keys.multi, (index, key) => + $.each this.searchMetaData().filter_keys.multi, (index, key) => @searchFilter[key] = this._builderSelectMultiValue(key) @restPost({ filter: JSON.stringify(@searchFilter), page: @pageNumber }).done(this.didSearch) @@ -239,6 +242,10 @@ context.JK.MusicianSearchFilter = class MusicianSearchFilter extends BaseSearchF init: (app) => super(app) + @screen.find('#btn-'+@searchType+'-search-builder').on 'click', => + this.showBuilder() + @screen.find('#btn-'+@searchType+'-search-reset').on 'click', => + this.resetFilter() renderSearchFilter: () => super() @@ -293,8 +300,8 @@ context.JK.MusicianSearchFilter = class MusicianSearchFilter extends BaseSearchF _populateAges: () => @screen.find('#search-filter-ages').empty() - ages_map = @searchMeta['ages']['map'] - $.each @searchMeta['ages']['keys'], (index, key) => + ages_map = this.searchMetaData()['ages']['map'] + $.each this.searchMetaData()['ages']['keys'], (index, key) => ageTemplate = @screen.find('#template-search-filter-setup-ages').html() selected = '' ageLabel = ages_map[key] @@ -491,3 +498,148 @@ context.JK.MusicianSearchFilter = class MusicianSearchFilter extends BaseSearchF registerResultsPagination: () => super() + + +context.JK.BandSearchFilter = class BandSearchFilter extends BaseSearchFilter + + constructor: () -> + super() + @searchType = 'band' + @searchTypeS = @searchType+'s' + @restGet = @rest.getBandSearchFilter + @restPost = @rest.postBandSearchFilter + @searchMeta = gon.band_search_meta + @searchSubType = 'to_join' + + init: (app) => + super(app) + + @screen.find('#btn-'+@searchType+'-search-builder-to_join').on 'click', => + this.showBuilderToJoin() + @screen.find('#btn-'+@searchType+'-search-builder-to_hire').on 'click', => + this.showBuilderToHire() + + showBuilderToJoin: () => + @searchSubType = 'to_join' + this.showBuilder() + + showBuilderToHire: () => + @searchSubType = 'to_hire' + this.showBuilder() + + searchMetaData: () => + @searchMeta[@searchSubType] + + renderSearchFilter: () => + super() + + _searchFilterArgsToJoin: () => + args = + tour_option: @searchFilter.data_blob.tour_option + skill_level: @searchFilter.data_blob.skill_level + play_commit: @searchFilter.data_blob.play_commit + band_type: @searchFilter.data_blob.band_type + concert_gigs: @searchFilter.data_blob.concert_gigs + + _searchFilterArgsToHire: () => + args = + skill_level: @searchFilter.data_blob.skill_level + concert_gigs: @searchFilter.data_blob.concert_gigs + perform_samples: @searchFilter.data_blob.perform_samples + max_cost: @searchFilter.data_blob.max_cost + free_gigs: @searchFilter.data_blob.free_gigs + + _populateSearchFilterToJoin: () => + this._populateInstruments() + this._populateSkill() + this._populateGigs() + this._populateBandType() + this._populatePlayCommit() + this._populateTourOption() + + _populateSearchFilterToHire: () => + + loadSearchFilter: (sFilter) => + super(sFilter) + + @searchFilter = JSON.parse(sFilter) + switch @searchSubType + when 'to_join' then args = _searchFilterArgsToJoin() + when 'to_hire' then args = _searchFilterArgsToHire() + + template = context.JK.fillTemplate(@screen.find('#template-band-search-filter-'+@searchSubType).html(), args) + + content_root = @screen.find('#band-search-filter-builder') + content_root.html template + + @screen.find('#btn-perform-band-search').on 'click', => + this.performSearch() + + @screen.find('#btn-band-search-cancel').on 'click', => + this.cancelFilter() + + this._populateGenres() + this._populateSortOrder() + + switch @searchSubType + when 'to_join' then _populateSearchFilterToJoin() + when 'to_hire' then _populateSearchFilterToHire() + + _populateSortOrder: () => + this._populateSelectIdentifier('sort_order') + + _populateGenres: () => + super() + + _populateInstruments: () => + super() + + willSearch: (reload) => + super(reload) + + didSearch: (response) => + super(response) + + resetFilter: () => + super() + + cancelFilter: () => + super() + + doRestGet: (query) => + super('subtype='+@searchSubType) + + performSearch: () => + super() + + renderResultsHeader: () => + super() + + renderResultsPage: () => + super() + this.renderResultsHeader() if @pageNumber == 1 + bands = @searchResults.bands + len = bands.length + if 0 == len + @screen.find('#band-search-filter-results-list-blank').show() + @screen.find('#band-search-filter-results-list-blank').html('No results found') + return + else + @screen.find('#band-search-filter-results-list-blank').hide() + + _bindMessageBand: () => + + _bindFriendBand: () => + + _bindFollowBand: () => + + _formatLocation: (band) -> + + friendRequestCallback: (user_id)=> + # TODO: + + paginate: () => + super() + + registerResultsPagination: () => + super() diff --git a/web/app/assets/stylesheets/client/band.css.scss b/web/app/assets/stylesheets/client/band.css.scss index 4a9ff616d..72f431151 100644 --- a/web/app/assets/stylesheets/client/band.css.scss +++ b/web/app/assets/stylesheets/client/band.css.scss @@ -350,4 +350,36 @@ label { margin-bottom:2px; } +} + +#musicians-screen { + + .builder-section { + padding: 10px; + margin-bottom: 20px; + } + + #bands-filter-to-join { + + .builder-section { + padding: 10px; + margin-bottom: 20px; + } + + .col-left { + float: left; + width: 50%; + margin-left: auto; + margin-right: auto; + } + + .col-right { + float: right; + width: 50%; + margin-left: auto; + margin-right: auto; + } + + } + } \ No newline at end of file diff --git a/web/app/controllers/api_search_controller.rb b/web/app/controllers/api_search_controller.rb index 0663265ff..be15b0074 100644 --- a/web/app/controllers/api_search_controller.rb +++ b/web/app/controllers/api_search_controller.rb @@ -7,7 +7,7 @@ class ApiSearchController < ApiController def index if 1 == params[Search::PARAM_MUSICIAN].to_i || 1 == params[Search::PARAM_BAND].to_i - query = params.clone + query = parasobj.clone query[:remote_ip] = request.remote_ip if 1 == query[Search::PARAM_MUSICIAN].to_i @search = Search.musician_filter(query, current_user) @@ -32,13 +32,35 @@ class ApiSearchController < ApiController end elsif request.post? - ms = MusicianSearch.user_search_filter(current_user) + sobj = MusicianSearch.user_search_filter(current_user) filter = params[:filter] if filter == 'reset' - @search = ms.reset_search_results + @search = sobj.reset_search_results else json = JSON.parse(filter, :create_additions => false) - @search = ms.search_results_page(json, [params[:page].to_i, 1].max) + @search = sobj.search_results_page(json, [params[:page].to_i, 1].max) + end + respond_with @search, responder: ApiResponder, status: 201, template: 'api_search/index' + end + end + + def bands + if request.get? + if params[:results] + @search = BandSearch.user_search_filter(current_user).search_results_page(params[:subtype]) + respond_with @search, responder: ApiResponder, status: 201, template: 'api_search/index' + else + render :json => BandSearch.search_filter_json(current_user, params[:subtype]), :status => 200 + end + + elsif request.post? + sobj = BandSearch.user_search_filter(current_user) + filter = params[:filter] + if filter == 'reset' + @search = sobj.reset_search_results(params[:subtype]) + else + json = JSON.parse(filter, :create_additions => false) + @search = sobj.search_results_page(json, [params[:page].to_i, 1].max) end respond_with @search, responder: ApiResponder, status: 201, template: 'api_search/index' end diff --git a/web/app/controllers/spikes_controller.rb b/web/app/controllers/spikes_controller.rb index 0edce85ce..069a2d757 100644 --- a/web/app/controllers/spikes_controller.rb +++ b/web/app/controllers/spikes_controller.rb @@ -69,7 +69,12 @@ class SpikesController < ApplicationController end def musician_search_filter - # gon.musician_search_meta = MusicianSearch::SEARCH_FILTER_META + # gon.musician_search_meta = MusicianSearch.search_filter_meta + render :layout => 'web' + end + + def band_search_filter + gon.band_search_meta = BandSearch.search_filter_meta render :layout => 'web' end diff --git a/web/app/helpers/client_helper.rb b/web/app/helpers/client_helper.rb index c3942e798..f6febfb1d 100644 --- a/web/app/helpers/client_helper.rb +++ b/web/app/helpers/client_helper.rb @@ -67,8 +67,8 @@ module ClientHelper gon.ftue_network_test_duration = Rails.application.config.ftue_network_test_duration gon.ftue_network_test_max_clients = Rails.application.config.ftue_network_test_max_clients gon.ftue_maximum_gear_latency = Rails.application.config.ftue_maximum_gear_latency - gon.musician_search_meta = MusicianSearch::SEARCH_FILTER_META - gon.band_search_meta = BandSearch::SEARCH_FILTER_META + gon.musician_search_meta = MusicianSearch.search_filter_meta + gon.band_search_meta = BandSearch.search_filter_meta # is this the native client or browser? @nativeClient = is_native_client? diff --git a/web/app/views/api_search/index.rabl b/web/app/views/api_search/index.rabl index ea256bf52..14a00b499 100644 --- a/web/app/views/api_search/index.rabl +++ b/web/app/views/api_search/index.rabl @@ -58,6 +58,40 @@ if @search.is_a?(MusicianSearch) last_jam_audio_latency(musician) end } + +elsif @search.is_a?(BandSearch) + + node :page_count do |foo| + @search.page_count + end + + child(:results => :bands) { + attributes :id, :name, :city, :state, :country, :photo_url, :biography, :logo_url, :website + + node :is_following do |band| + @search.is_follower?(band) + end + + node :biography do |band| + band.biography.nil? ? "" : band.biography + end + + child :genres => :genres do + attributes :genre_id, :description + end + + child :users => :players do |pl| + node :user_id do |uu| uu.id end + node :photo_url do |uu| uu.photo_url end + node :name do |uu| uu.name end + node :instruments do |uu| uu.instruments.map(&:id).join(',') end + end + + node :follow_count do |band| @search.follow_count(band) end + node :recording_count do |band| @search.record_count(band) end + node :session_count do |band| @search.session_count(band) end + } + else if @search.session_invite_search? diff --git a/web/app/views/clients/_band_search_filter.html.slim b/web/app/views/clients/_band_search_filter.html.slim new file mode 100644 index 000000000..a80cd9f1d --- /dev/null +++ b/web/app/views/clients/_band_search_filter.html.slim @@ -0,0 +1,94 @@ +.content-body-scroller + div#band-search-filter-builder.content-wrapper + + div#band-search-filter-results.content-wrapper + div#band-search-filter-results-header + a#btn-band-search-builder-to_join.button-orange href="#" SEARCH FOR BAND TO JOIN + a#btn-band-search-reset-to_hire.button-grey href="#" SEARCH FOR BAND TO HIRE + div#band-search-filter-description + div.clearall + div#band-search-filter-spinner.spinner-large + + div#band-search-filter-results-wrapper + div#band-search-filter-results-list-blank + div#band-search-filter-results-list.content-wrapper + div.paginate-wait + Fetching more results... + div.spinner-small + +script#template-band-search-filter-to_join type="text/template" + #bands-filter-to_join + #band-search-filter-builder-top.builder-section + .col-left + h2 search bands + .col-right.builder-sort-order + .text-label Sort Results By: + select.easydropdown name="sort_order" + option selected="selected" value="{sort_order}" {sort_order} + .clearall + + #band-search-filter-builder-middle1.builder-section + .col-left + .field + label for="search-filter-genres" Genres: + .search-filter-setup-genres.band-setup-genres + table#search-filter-genres cellpadding="10" cellspacing="6" width="100%" + + .col-right + .field + label for="search-filter-instruments" + | Instruments & Skill Level: + .search-filter-setup-instruments.band-setup-genres.builder-instruments + table#search-filter-instruments cellpadding="10" cellspacing="6" width="100%" + .clearall + + #band-search-filter-builder-middle2.builder-section + .col-left + .field.builder-selector + label Type: + select.easydropdown name="band_type" + option selected="selected" value="{band_type}" {band_type} + + .field.builder-selector + label Play Commitment: + select.easydropdown name="play_commit" + option selected="selected" value="{play_commit}" {play_commit} + + .col-right + .field.builder-selector + label Status: + select.easydropdown name="skill_level" + option selected="selected" value="{skill_level}" {skill_level} + + .field.builder-selector + label Concert Gigs Played: + select.easydropdown name="concert_gigs" + option selected="selected" value="{concert_gigs}" {concert_gigs} + + .field.builder-selector + label Touring Option: + select.easydropdown name="tour_option" + option selected="selected" value="{tour_option}" {tour_option} + .clearall + + .clearall + #band-search-filter-builder-bottom.builder-section.builder-action-buttons + .col-right + a#btn-perform-band-search.builder-button.button-orange href="#" SEARCH + a#btn-band-search-cancel.builder-button.button-grey href="#" CANCEL + +script#template-search-filter-setup-instrument type="text/template" + tr data-instrument-id="{id}" + td {description} + td align="right" width="50%" + select.proficiency_selector name="proficiency" + option value="1" Beginner + option value="2" Intermediate + option value="3" Expert + +script#template-search-filter-setup-genres type="text/template" + tr + td {description} + +/! Session Row Template +script#template-search-band-row type="text/template" diff --git a/web/app/views/clients/_bands.html.erb b/web/app/views/clients/_bands.html.erb deleted file mode 100644 index ae7bdbf5c..000000000 --- a/web/app/views/clients/_bands.html.erb +++ /dev/null @@ -1,86 +0,0 @@ - -<%= content_tag(:div, :layout => 'screen', 'layout-id' => 'bands', :class => "screen secondary", :id => "bands-screen") do -%> - <%= content_tag(:div, :class => :content) do -%> - <%= content_tag(:div, :class => 'content-head') do -%> - <%= content_tag(:div, image_tag("content/icon_bands.png", {:height => 19, :width => 19}), :class => 'content-icon') %> - <%= content_tag(:h1, 'bands') %> - <%= render "screen_navigation" %> - <% end -%> - <%= content_tag(:div, :class => 'content-body') do -%> - <%= form_tag('', {:id => 'find-band-form', :class => 'inner-content'}) do -%> - <%= render(:partial => "web_filter", :locals => {:search_type => Search::PARAM_BAND}) %> - <%= content_tag(:div, :class => 'filter-body') do %> - <%= content_tag(:div, :class => 'content-body-scroller') do -%> - <%= content_tag(:div, content_tag(:div, '', :id => 'band-filter-results', :class => 'filter-results'), :class => 'content-wrapper') %> - <% end -%> - <% end -%> - <% end -%> - <% end -%> - <% end -%> -<% end -%> - - - - - - - - - - diff --git a/web/app/views/clients/_bands.html.slim b/web/app/views/clients/_bands.html.slim new file mode 100644 index 000000000..c472fbe39 --- /dev/null +++ b/web/app/views/clients/_bands.html.slim @@ -0,0 +1,140 @@ +#bands-screen.screen.secondary layout="screen" layout-id="bands" + .content + .content-head + .content-icon + img alt="Icon_bands" height="19" src="/assets/content/icon_bands.png" width="19" / + h1 bands + = render "screen_navigation" + .content-body + = render "clients/band_search_filter" + +script#template-band-search-filter-to_join type="text/template" + #bands-filter-to_join + #band-search-filter-builder-top.builder-section + .col-left + h2 search bands + .col-right.builder-sort-order + .text-label Sort Results By: + select.easydropdown name="sort_order" + option selected="selected" value="{sort_order}" {sort_order} + .clearall + + #band-search-filter-builder-middle1.builder-section + .col-left + .field + label for="search-filter-genres" Genres: + .search-filter-setup-genres.band-setup-genres + table#search-filter-genres cellpadding="10" cellspacing="6" width="100%" + + .col-right + .field + label for="search-filter-instruments" + | Instruments & Skill Level: + .search-filter-setup-instruments.band-setup-genres.builder-instruments + table#search-filter-instruments cellpadding="10" cellspacing="6" width="100%" + .clearall + + #band-search-filter-builder-middle2.builder-section + .col-left + .field.builder-selector + label Type: + select.easydropdown name="band_type" + option selected="selected" value="{band_type}" {band_type} + + .field.builder-selector + label Play Commitment: + select.easydropdown name="play_commit" + option selected="selected" value="{play_commit}" {play_commit} + + .col-right + .field.builder-selector + label Status: + select.easydropdown name="skill_level" + option selected="selected" value="{skill_level}" {skill_level} + + .field.builder-selector + label Concert Gigs Played: + select.easydropdown name="concert_gigs" + option selected="selected" value="{concert_gigs}" {concert_gigs} + + .field.builder-selector + label Touring Option: + select.easydropdown name="tour_option" + option selected="selected" value="{tour_option}" {tour_option} + + .clearall + + .clearall + #band-search-filter-builder-bottom.builder-section.builder-action-buttons + .col-right + a#btn-perform-band-search.builder-button.button-orange href="#" SEARCH + a#btn-band-search-cancel.builder-button.button-grey href="#" CANCEL + +/! Session Row Template +script#template-search-band-row type="text/template" + .profile-band-list-result.band-list-result + .f11 + .left style="width:63px;margin-top:-12px;" + /! avatar + .avatar-small + img src="{avatar_url}" / + .right.mband-players style="width:265px; margin-top:-4px;" + table.musicians cellpadding="0" cellspacing="5" + | {band_player_template} + div style="margin-left: 63px; margin-right: 275px;margin-top: 12px;" + .first-row data-hint="top-row" + .lcol.left + /! name and location + .result-name + | {band_name} + .result-location + | {band_location} + br / + #result_genres.nowrap.mt10 + | {genres} + .whitespace + .biography + | {biography} + .clearleft + .button-row + .lcol.stats.left + span.follower-count + | {follow_count} + img src="../assets/content/icon_followers.png" width="22" height="12" align="absmiddle" style="margin-right:4px;" / + span.recording-count + | {recording_count} + img src="../assets/content/icon_recordings.png" width="12" height="13" align="absmiddle" style="margin-right:4px;" / + span.session-count + | {session_count} + img src="../assets/content/icon_session_tiny.png" width="12" height="12" align="absmiddle" / + .clearall + .result-list-button-wrapper data-band-id="{band_id}" + | {band_action_template} + .clearall + +script#template-search-band-action-btns type="text/template" + a.button-orange smallbutton href="{profile_url}" + PROFILE + a class="{button_follow} smallbutton search-m-follow" href="#" + FOLLOW + +script#template-search-band-edit-btns type="text/template" + a href="{profile_url}" class="button-orange smallbutton" + PROFILE + a href="{band_edit_url}" class="button-orange smallbutton" + EDIT BAND + a href="{band_member_url}" class="button-orange smallbutton" + INVITE + +script#template-search-band-player-info type="text/template" + tr + td + a.avatar-tiny href="{profile_url}" user-id="{user_id}" hoveraction="musician" + img src="{avatar_url}" / + td style="padding: 0 4px;width:88px" + a user-id="{user_id}" hoveraction="musician" href="{profile_url}" + strong + | {player_name} + td.instruments + | {player_instruments} + diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index 5654778b9..f894825f9 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -296,8 +296,10 @@ // var findMusicianScreen = new JK.FindMusicianScreen(JK.app); //findMusicianScreen.initialize(JK.TextMessageDialogInstance); - var findBandScreen = new JK.FindBandScreen(JK.app); - findBandScreen.initialize(); + var findBandScreen = new JK.BandSearchFilter(); + findBandScreen.init(JK.app); + // var findBandScreen = new JK.FindBandScreen(JK.app); + // findBandScreen.initialize(); var sessionScreen = new JK.SessionScreen(JK.app); sessionScreen.initialize(localRecordingsDialog, recordingFinishedDialog, JK.FriendSelectorDialogInstance); diff --git a/web/app/views/spikes/band_search_filter.html.slim b/web/app/views/spikes/band_search_filter.html.slim new file mode 100644 index 000000000..9dff2e51e --- /dev/null +++ b/web/app/views/spikes/band_search_filter.html.slim @@ -0,0 +1,15 @@ += javascript_include_tag "profile_utils" += javascript_include_tag "member_search_filter" += stylesheet_link_tag "client/band" +#band_search_spike += render "clients/band_search_filter" + +javascript: + var initialized = false; + $(document).on('JAMKAZAM_READY', function(e, data) { + setTimeout(function() { + window.band_search_filter = new JK.BandSearchFilter(); + band_search_filter.init(); + band_search_filter.afterShow(); + }, 1) + }); diff --git a/web/config/routes.rb b/web/config/routes.rb index bb3aadf10..2cd392338 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -111,6 +111,7 @@ SampleApp::Application.routes.draw do match '/site_validate', to: 'spikes#site_validate' match '/recording_source', to: 'spikes#recording_source' match '/musician_search_filter', to: 'spikes#musician_search_filter' + match '/band_search_filter', to: 'spikes#band_search_filter' # junk pages match '/help', to: 'static_pages#help' @@ -451,6 +452,7 @@ SampleApp::Application.routes.draw do # search match '/search' => 'api_search#index', :via => :get match '/search/musicians' => 'api_search#musicians', :via => [:get, :post] + match '/search/bands' => 'api_search#bands', :via => [:get, :post] # join requests match '/join_requests/:id' => 'api_join_requests#show', :via => :get, :as => 'api_join_request_detail' diff --git a/web/lib/tasks/sample_data.rake b/web/lib/tasks/sample_data.rake index 88c496ddf..0da3673f7 100644 --- a/web/lib/tasks/sample_data.rake +++ b/web/lib/tasks/sample_data.rake @@ -128,7 +128,7 @@ end def make_band_members Band.find_each do |bb| User.order('RANDOM()').limit(4).each do |uu| - BandMusician.create!({:user_id => uu.id, :band_id => bb.id}) + BandMusician.create({:user_id => uu.id, :band_id => bb.id}) end end end