diff --git a/.gitignore b/.gitignore index 2773be5d3..e82e8f786 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ working.png ruby/.rails5-gems web/.rails5-gems websocket-gateway/.rails5-gems +.pg_data/ diff --git a/jam-ui/.python-version b/jam-ui/.python-version new file mode 100644 index 000000000..a61649269 --- /dev/null +++ b/jam-ui/.python-version @@ -0,0 +1 @@ +2.7.18 diff --git a/jam-ui/cypress.config.js b/jam-ui/cypress.config.js new file mode 100644 index 000000000..999a37a56 --- /dev/null +++ b/jam-ui/cypress.config.js @@ -0,0 +1,22 @@ +module.exports = { + env: { + legacyBaseUrl: "http://www.jamkazam.local:3000", + apiBaseUrl: "http://www.jamkazam.local:3000/api", + }, + + e2e: { + // We've imported your old cypress plugins here. + // You may want to clean this up later by importing these. + setupNodeEvents(on, config) { + return require("./cypress/plugins/index.js")(on, config); + }, + baseUrl: "http://beta.jamkazam.local:4000", + }, + + component: { + devServer: { + framework: "react", + bundler: "webpack", + }, + }, +}; diff --git a/jam-ui/cypress.json b/jam-ui/cypress.json deleted file mode 100644 index 4a1e6b4ef..000000000 --- a/jam-ui/cypress.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "baseUrl": "http://beta.jamkazam.local:4000", - "env": { - "legacyBaseUrl": "http://www.jamkazam.local:3000", - "apiBaseUrl": "http://www.jamkazam.local:3000/api" - } -} diff --git a/jam-ui/cypress/integration/auth/login.js b/jam-ui/cypress/e2e/auth/login.cy.js similarity index 100% rename from jam-ui/cypress/integration/auth/login.js rename to jam-ui/cypress/e2e/auth/login.cy.js diff --git a/jam-ui/cypress/integration/friends/friends-page.spec.js b/jam-ui/cypress/e2e/friends/friends-page.cy.js similarity index 100% rename from jam-ui/cypress/integration/friends/friends-page.spec.js rename to jam-ui/cypress/e2e/friends/friends-page.cy.js diff --git a/jam-ui/cypress/integration/layout/navigation.spec.js b/jam-ui/cypress/e2e/layout/navigation.cy.js similarity index 100% rename from jam-ui/cypress/integration/layout/navigation.spec.js rename to jam-ui/cypress/e2e/layout/navigation.cy.js diff --git a/jam-ui/cypress/support/component-index.html b/jam-ui/cypress/support/component-index.html new file mode 100644 index 000000000..ac6e79fd8 --- /dev/null +++ b/jam-ui/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + \ No newline at end of file diff --git a/jam-ui/cypress/support/component.js b/jam-ui/cypress/support/component.js new file mode 100644 index 000000000..0d9eef905 --- /dev/null +++ b/jam-ui/cypress/support/component.js @@ -0,0 +1,27 @@ +// *********************************************************** +// This example support/component.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +import { mount } from 'cypress/react' + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount() \ No newline at end of file diff --git a/jam-ui/cypress/support/index.js b/jam-ui/cypress/support/e2e.js similarity index 100% rename from jam-ui/cypress/support/index.js rename to jam-ui/cypress/support/e2e.js diff --git a/jam-ui/package-lock.json b/jam-ui/package-lock.json index c38b0b51f..172964b85 100644 --- a/jam-ui/package-lock.json +++ b/jam-ui/package-lock.json @@ -1176,6 +1176,12 @@ "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz", "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==" }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, "@emotion/cache": { "version": "10.0.29", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", @@ -3097,6 +3103,27 @@ "@xtuc/long": "4.2.2" } }, + "@webpack-cli/configtest": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", + "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "dev": true + }, + "@webpack-cli/info": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", + "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", + "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "dev": true + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -7185,6 +7212,12 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" }, + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true + }, "errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -8209,6 +8242,12 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true + }, "faye-websocket": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", @@ -19706,6 +19745,164 @@ } } }, + "webpack-cli": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", + "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "cross-spawn": "^7.0.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "webpack-dev-middleware": { "version": "3.7.3", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", @@ -19939,6 +20136,44 @@ } } }, + "webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "dependencies": { + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + } + } + }, "webpack-sources": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", @@ -20073,6 +20308,12 @@ } } }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", diff --git a/jam-ui/package.json b/jam-ui/package.json index 8391b669b..2947d7bba 100644 --- a/jam-ui/package.json +++ b/jam-ui/package.json @@ -105,6 +105,7 @@ "gulp-sass": "^4.1.0", "gulp-sourcemaps": "^2.6.5", "prettier": "1.17.1", - "swiper": "^6.8.2" + "swiper": "^6.8.2", + "webpack-cli": "^4.10.0" } } diff --git a/jam-ui/src/components/page/JKPeopleFilter.js b/jam-ui/src/components/page/JKPeopleFilter.js index f3eb9d085..3a42697ef 100644 --- a/jam-ui/src/components/page/JKPeopleFilter.js +++ b/jam-ui/src/components/page/JKPeopleFilter.js @@ -49,7 +49,7 @@ function JKPeopleFilter() { instruments: [], genres: [], joined_within_days: '-1', - active_within_days: '-1', + active_within_days: { value: '30', label: 'Within Last 30 Days' }, from_location: false, } }); diff --git a/ruby/lib/jam_ruby/models/base_search.rb b/ruby/lib/jam_ruby/models/base_search.rb index 8e8ac9872..7ba937f47 100644 --- a/ruby/lib/jam_ruby/models/base_search.rb +++ b/ruby/lib/jam_ruby/models/base_search.rb @@ -200,10 +200,14 @@ module JamRuby rel end + def filter_includes(rel) + rel + end + def user_search_results(user_ids) rel = do_filter(user_ids) - rel = self.search_includes(rel) - process_results_page(rel.all) + rel = self.filter_includes(rel) + process_results_page(rel.all, true) #skip_counters = true end def search_results_page(filter=nil, page=1, user_ids=nil) diff --git a/ruby/lib/jam_ruby/models/musician_search.rb b/ruby/lib/jam_ruby/models/musician_search.rb index b03562ca6..76da51354 100644 --- a/ruby/lib/jam_ruby/models/musician_search.rb +++ b/ruby/lib/jam_ruby/models/musician_search.rb @@ -176,9 +176,11 @@ module JamRuby #NOTE: we can change to this once we upgrade postgresql #rel = rel.where(id: user_ids).where('users.id <> ?', self.user.id).order("array_position(ARRAY[#{user_ids.map { |i| "'#{i}'" }.join(',')}], id::TEXT)") - #rel = self._sort_by_ids_ordinality(rel, user_ids) + #rel = self._sort_by_ids_ordinality(rel, user_ids) end end + + rel = rel.select("users.*, (SELECT count(friendships.id) > 0 AS is_friend FROM friendships WHERE friendships.user_id = users.id AND friendships.friend_id = '#{self.user.id}'), (SELECT count(follows.id) > 0 AS is_following FROM follows WHERE follows.user_id = users.id AND follows.followable_id = '#{self.user.id}' AND follows.followable_type = 'JamRuby::User'), (SELECT count(friend_requests.id) > 0 as pending_friend_request from friend_requests WHERE (friend_requests.user_id = '#{self.user.id}' AND friend_requests.friend_id = users.id) OR (friend_requests.user_id = users.id AND friend_requests.friend_id = '#{self.user.id}') )") rel end @@ -203,35 +205,41 @@ module JamRuby rel.includes([:instruments, :followings, :friends]) end - def process_results_page(_results) + def filter_includes(rel) + rel.includes([:instruments, :genres]) + end + + def process_results_page(_results, skip_counters = false) @results = _results + @user_counters = {} and return self unless user - @user_counters = @results.inject({}) { |hh,val| hh[val.id] = []; hh } - mids = "'#{@results.map(&:id).join("','")}'" + unless skip_counters + @user_counters = @results.inject({}) { |hh,val| hh[val.id] = []; hh } + mids = "'#{@results.map(&:id).join("','")}'" - # this gets counts for each search result on friends/follows/records/sessions - @results.each do |uu| - counters = { } - counters[COUNT_FRIEND] = Friendship.where(:user_id => uu.id).count - counters[COUNT_FOLLOW] = Follow.where(:followable_id => uu.id).count - counters[COUNT_RECORD] = ClaimedRecording.where(:user_id => uu.id).count - counters[COUNT_SESSION] = MusicSession.where(:user_id => uu.id).count - @user_counters[uu.id] << counters + # this gets counts for each search result on friends/follows/records/sessions + @results.each do |uu| + counters = { } + counters[COUNT_FRIEND] = Friendship.where(:user_id => uu.id).count + counters[COUNT_FOLLOW] = Follow.where(:followable_id => uu.id).count + counters[COUNT_RECORD] = ClaimedRecording.where(:user_id => uu.id).count + counters[COUNT_SESSION] = MusicSession.where(:user_id => uu.id).count + @user_counters[uu.id] << counters + end + + # this section determines follow/like/friend status for each search result + # so that action links can be activated or not + rel = User.select("users.id AS uid") + rel = rel.joins("LEFT JOIN follows ON follows.user_id = '#{user.id}'") + rel = rel.where(["users.id IN (#{mids}) AND follows.followable_id = users.id"]) + rel.all.each { |val| @user_counters[val.uid] << RESULT_FOLLOW } + + rel = User.select("users.id AS uid") + rel = rel.joins("LEFT JOIN friendships AS friends ON friends.friend_id = '#{user.id}'") + rel = rel.where(["users.id IN (#{mids}) AND friends.user_id = users.id"]) + rel.all.each { |val| @user_counters[val.uid] << RESULT_FRIEND } end - - # this section determines follow/like/friend status for each search result - # so that action links can be activated or not - rel = User.select("users.id AS uid") - rel = rel.joins("LEFT JOIN follows ON follows.user_id = '#{user.id}'") - rel = rel.where(["users.id IN (#{mids}) AND follows.followable_id = users.id"]) - rel.all.each { |val| @user_counters[val.uid] << RESULT_FOLLOW } - - rel = User.select("users.id AS uid") - rel = rel.joins("LEFT JOIN friendships AS friends ON friends.friend_id = '#{user.id}'") - rel = rel.where(["users.id IN (#{mids}) AND friends.user_id = users.id"]) - rel.all.each { |val| @user_counters[val.uid] << RESULT_FRIEND } - self end diff --git a/web/app/controllers/api_search_controller.rb b/web/app/controllers/api_search_controller.rb index bc67272be..f0e5a7b92 100644 --- a/web/app/controllers/api_search_controller.rb +++ b/web/app/controllers/api_search_controller.rb @@ -113,9 +113,9 @@ class ApiSearchController < ApiController # filter_params.merge!(genres: genres) # end - beginner = ActiveRecord::Type::Boolean.new.type_cast_from_user(params[:proficiency_beginner]) - intermediate = ActiveRecord::Type::Boolean.new.type_cast_from_user(params[:proficiency_intermediate]) - expert = ActiveRecord::Type::Boolean.new.type_cast_from_user(params[:proficiency_expert]) + beginner = ActiveRecord::Type::Boolean.new.type_cast_from_user(params[:proficiency_beginner]) + intermediate = ActiveRecord::Type::Boolean.new.type_cast_from_user(params[:proficiency_intermediate]) + expert = ActiveRecord::Type::Boolean.new.type_cast_from_user(params[:proficiency_expert]) proficiency_levels = [] proficiency_levels.push(1) if beginner @@ -147,8 +147,7 @@ class ApiSearchController < ApiController @latency_data = result[:data] @offset = result[:offset] - user_ids = @latency_data.map{ |l_data| l_data[:user_id] } - + user_ids = @latency_data.map{ |l_data| l_data[:user_id] } #end # Bugsnag.notify("search_users_benchmark") do |report| @@ -158,6 +157,7 @@ class ApiSearchController < ApiController sobj = MusicianSearch.user_search_filter(current_user) #@search = sobj.search_results_page(filter_params, page, user_ids) + #debugger @search = sobj.user_search_results(user_ids) respond_with @search, responder: ApiResponder, status: 201, template: 'api_search/filter' diff --git a/web/app/views/api_search/filter.rabl b/web/app/views/api_search/filter.rabl index 4fc5a360e..8ba80bccd 100644 --- a/web/app/views/api_search/filter.rabl +++ b/web/app/views/api_search/filter.rabl @@ -25,19 +25,19 @@ node :is_blank_filter do |foo| end child(:results => :musicians) { - attributes :id, :first_name, :last_name, :name, :city, :state, :country, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score + attributes :id, :first_name, :last_name, :name, :city, :state, :country, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score, :is_friend, :is_following, :pending_friend_request - node :is_friend do |musician| - @search.is_friend?(musician) - end + # node :is_friend do |musician| + # @search.is_friend?(musician) + # end - node :is_following do |musician| - @search.is_follower?(musician) - end + # node :is_following do |musician| + # @search.is_follower?(musician) + # end - node :pending_friend_request do |musician| - musician.pending_friend_request?(current_user) - end + # node :pending_friend_request do |musician| + # musician.pending_friend_request?(current_user) + # end node :biography do |musician| musician.biography.nil? ? "" : musician.biography @@ -47,16 +47,16 @@ child(:results => :musicians) { attributes :instrument_id, :description, :proficiency_level, :priority end - child :top_followings => :followings do |uf| - node :user_id do |uu| uu.id end - node :photo_url do |uu| uu.photo_url end - node :name do |uu| uu.name end - end + # child :top_followings => :followings do |uf| + # node :user_id do |uu| uu.id end + # node :photo_url do |uu| uu.photo_url end + # node :name do |uu| uu.name end + # end - node :friend_count do |musician| @search.friend_count(musician) end - node :follow_count do |musician| @search.follow_count(musician) end - node :recording_count do |musician| @search.record_count(musician) end - node :session_count do |musician| @search.session_count(musician) end + # node :friend_count do |musician| @search.friend_count(musician) end + # node :follow_count do |musician| @search.follow_count(musician) end + # node :recording_count do |musician| @search.record_count(musician) end + # node :session_count do |musician| @search.session_count(musician) end node :audio_latency do |musician| last_jam_audio_latency(musician) @@ -65,10 +65,19 @@ child(:results => :musicians) { node :latency_data do |musician| if latency = @latency_data.detect{|l_data| l_data[:user_id] == musician.id } + audio_latency = latency[:audio_latency].to_i + internet_latency = latency[:ars_internet_latency].to_i + total_letency = latency[:ars_total_latency] + #sometimes neo4j returns 0 for audio latency. this is not correct. + #when this happens as a temporary hack we default audio latency to 5. + if audio_latency <= 0 + audio_latency = 5 + total_letency = audio_latency + internet_latency + end { - audio_latency: latency[:audio_latency], - ars_internet_latency: latency[:ars_internet_latency], - ars_total_latency: latency[:ars_total_latency] + audio_latency: audio_latency, + ars_internet_latency: internet_latency, + ars_total_latency: total_letency } end if @latency_data end diff --git a/web/spec/requests/musician_filter_api_spec.rb b/web/spec/requests/musician_filter_api_spec.rb index 677b79872..702ac5f0c 100644 --- a/web/spec/requests/musician_filter_api_spec.rb +++ b/web/spec/requests/musician_filter_api_spec.rb @@ -13,7 +13,8 @@ describe "Musician Filter API", type: :request do let(:user5) { FactoryGirl.create(:user) } let(:user6) { FactoryGirl.create(:user) } let(:user7) { FactoryGirl.create(:user) } - + let(:user8) { FactoryGirl.create(:user) } + let(:latency_data_uri) { /\S+\/search_users/ } let(:response_body) { mock_latency_response([ @@ -23,7 +24,8 @@ describe "Musician Filter API", type: :request do { user: user4, ars_total_latency: 60.0, ars_internet_latency: 30, audio_latency: 30.0 }, #FAIR { user: user5, ars_total_latency: 60.1, ars_internet_latency: 30.1, audio_latency: 30 }, #HIGH { user: user6, ars_total_latency: 100.0, ars_internet_latency: 50.0, audio_latency: 50.0 }, #HIGH - { user: user7, ars_total_latency: -2, ars_internet_latency: -1, audio_latency: -1 } #UNKNOWN + { user: user7, ars_total_latency: -2, ars_internet_latency: -1, audio_latency: -1 }, #UNKNOWN + { user: user8, ars_total_latency: 10, ars_internet_latency: 5, audio_latency: 0 } #GOOD (NOTE: audio_latency from neo4j is 0 here) ]) } @@ -128,22 +130,28 @@ describe "Musician Filter API", type: :request do it "get all musicians" do get '/api/search/musicians.json?results=true' - expect(JSON.parse(response.body)["musicians"].size).to eq(7) + expect(JSON.parse(response.body)["musicians"].size).to eq(8) end it "filter musicians when no latency option is selected" do post '/api/filter.json', { latency_good: false, latency_fair: false, latency_high: false } - expect(JSON.parse(response.body)["musicians"].size).to eq(7) + expect(JSON.parse(response.body)["musicians"].size).to eq(8) expect(JSON.parse(response.body)["musicians"][0]["latency_data"]).not_to eq(nil) expect(JSON.parse(response.body)["musicians"][0]["latency_data"]["audio_latency"]).not_to eq(nil) expect(JSON.parse(response.body)["musicians"][0]["latency_data"]["ars_internet_latency"]).not_to eq(nil) expect(JSON.parse(response.body)["musicians"][0]["latency_data"]["ars_total_latency"]).not_to eq(nil) + expect(JSON.parse(response.body)["musicians"][0]["latency_data"]["audio_latency"]).to eq(5) + end + + it "set audio latency to 5ms when the returned value is 0" do + post '/api/filter.json', { latency_good: false, latency_fair: false, latency_high: false } + expect(JSON.parse(response.body)["musicians"][7]["latency_data"]["audio_latency"]).to eq(5) end it "filter musicians for all latency options" do post '/api/filter.json', { latency_good: true, latency_fair: true, latency_high: true } - expect(JSON.parse(response.body)["musicians"].size).to eq(6) + expect(JSON.parse(response.body)["musicians"].size).to eq(7) expect(JSON.parse(response.body)["musicians"][0]["latency_data"]).not_to eq(nil) expect(JSON.parse(response.body)["musicians"][0]["latency_data"]["audio_latency"]).not_to eq(nil) expect(JSON.parse(response.body)["musicians"][0]["latency_data"]["ars_internet_latency"]).not_to eq(nil) @@ -156,6 +164,7 @@ describe "Musician Filter API", type: :request do expect(JSON.parse(response.body)["musicians"][3]["id"]).to eq(user4.id) expect(JSON.parse(response.body)["musicians"][4]["id"]).to eq(user5.id) expect(JSON.parse(response.body)["musicians"][5]["id"]).to eq(user6.id) + expect(JSON.parse(response.body)["musicians"][6]["id"]).to eq(user8.id) end it "filter GOOD latency users" do @@ -163,7 +172,7 @@ describe "Musician Filter API", type: :request do expect(response.content_type).to eq("application/json") expect(response).to render_template(:filter) expect(response).to have_http_status(:created) - expect(JSON.parse(response.body)["musicians"].size).to eq(2) + expect(JSON.parse(response.body)["musicians"].size).to eq(3) #test latency data expect(JSON.parse(response.body)["musicians"][0]["latency_data"]).not_to eq(nil) @@ -184,17 +193,17 @@ describe "Musician Filter API", type: :request do it "filter GOOD and FAIR latency musicians" do post '/api/filter.json', { latency_good: true, latency_fair: true, latency_high: false } - expect(JSON.parse(response.body)["musicians"].size).to eq(4) + expect(JSON.parse(response.body)["musicians"].size).to eq(5) end it "filter GOOD and HIGH latency musicians" do post '/api/filter.json', { latency_good: true, latency_fair: false, latency_high: true } - expect(JSON.parse(response.body)["musicians"].size).to eq(4) + expect(JSON.parse(response.body)["musicians"].size).to eq(5) end it "filter GOOD, FAIR and HIGH latency musicians" do post '/api/filter.json', { latency_good: true, latency_fair: true, latency_high: true } - expect(JSON.parse(response.body)["musicians"].size).to eq(6) + expect(JSON.parse(response.body)["musicians"].size).to eq(7) end it "filter musicians by genres" do