diff --git a/ruby/lib/jam_ruby/models/review.rb b/ruby/lib/jam_ruby/models/review.rb
index 4fe6e755b..48cdb7148 100644
--- a/ruby/lib/jam_ruby/models/review.rb
+++ b/ruby/lib/jam_ruby/models/review.rb
@@ -17,9 +17,42 @@ module JamRuby
validates :target, presence: true
validates :user_id, presence: true
validates :target_id, uniqueness: {scope: :user_id, message: "There is already a review for this User and Target."}
+ validate :requires_lesson
after_save :reduce
+ def requires_lesson
+ if target_type == 'JamRuby::User'
+
+ # you are rating a student
+ lesson = LessonSession.joins(:music_session).where('music_sessions.user_id = ?', target.id).where(teacher_id: user.id).first
+ if lesson.nil?
+ errors.add(:target, "You must have at least scheduled or been in a lesson with this student")
+ end
+
+ elsif target_type == "JamRuby::Teacher"
+
+ # you are rating a teacher
+ lesson = LessonSession.joins(:music_session).where('music_sessions.user_id = ?', user.id).where(teacher_id: target.user.id).first
+ if lesson.nil?
+ errors.add(:target, "You must have at least scheduled or been in a lesson with this teacher")
+ end
+ end
+ end
+
+ def self.create_or_update(params)
+ review = Review.where(user_id: params[:user].id).where(target_id: params[:target].id).where(target_type: params[:target].class.to_s).first
+
+ if review
+ review.description = params[:description]
+ review.rating = params[:rating]
+ review.save
+ else
+ review = Review.create(params)
+ end
+
+ review
+ end
def self.create(params)
review = Review.new
review.target = params[:target]
@@ -81,7 +114,7 @@ module JamRuby
def reduce
ReviewSummary.transaction do
- ReviewSummary.where(target_type: target_type, target_id: target_id).destroy_all
+ ReviewSummary.where(target_type: target_type, target_id: target_id).delete_all
Review.select("target_id, target_type AS target_type, AVG(rating) as avg_rating, count(*) as review_count, SUM(CASE WHEN rating>=3.0 THEN 1 ELSE 0 END) AS pos_count")
.where("deleted_at IS NULL")
@@ -89,15 +122,22 @@ module JamRuby
.group("target_type, target_id")
.each do |r|
wilson_score = Review.ci_lower_bound(r.pos_count, r.review_count)
- ReviewSummary.create!(
+
+ summary = ReviewSummary.create(
target_id: r.target_id,
target_type: r.target_type,
avg_rating: r.avg_rating,
wilson_score: wilson_score,
review_count: r.review_count
)
+ if summary.errors.any?
+ puts "review summary unable to be created #{summary.errors.inspect}"
+ raise "review summary unable to be created #{summary.errors.inspect}"
+ end
end
end
+
+ return true
end
end
end
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby/models/review_summary.rb b/ruby/lib/jam_ruby/models/review_summary.rb
index fb3833f5d..b0aef4711 100644
--- a/ruby/lib/jam_ruby/models/review_summary.rb
+++ b/ruby/lib/jam_ruby/models/review_summary.rb
@@ -5,7 +5,7 @@ module JamRuby
validates :avg_rating, presence:true, numericality: true
validates :review_count, presence:true, numericality: {only_integer: true}
- validates :wilson_score, presence:true, numericality: {greater_than:0, less_than:1}
+ validates :wilson_score, presence:true, numericality: {greater_than_or_equal_to:0, less_than_or_equal_to:1}
validates :target_id, presence:true, uniqueness:true
class << self
diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb
index 85c9cd061..2421a5c3c 100644
--- a/ruby/lib/jam_ruby/models/user.rb
+++ b/ruby/lib/jam_ruby/models/user.rb
@@ -2113,11 +2113,11 @@ module JamRuby
end
def has_rated_teacher(teacher)
- teacher_rating(teacher).count > 0
+ teacher_rating(teacher)
end
def has_rated_student(student)
- student_rating(student).count > 0
+ Review.where(target_id: student.id).where(target_type: "JamRuby::User").count > 0
end
def teacher_rating(teacher)
@@ -2126,9 +2126,11 @@ module JamRuby
end
Review.where(target_id: teacher.id).where(target_type: teacher.class.to_s)
end
-
- def student_rating(student)
- Review.where(target_id: student.id).where(target_type: "JamRuby::User")
+ def teacher_rating(teacher)
+ if teacher.is_a?(JamRuby::User)
+ teacher = teacher.teacher
+ end
+ Review.where(target_id: teacher.id).where(target_type: teacher.class.to_s)
end
def has_rated_student(student)
@@ -2140,7 +2142,7 @@ module JamRuby
end
def ratings_url
- "#{APP_CONFIG.external_root_url}/client?selected=ratings#/profile/teacher/#{id}"
+ "#{APP_CONFIG.external_root_url}/client?tile=ratings#/profile/teacher/#{id}"
end
def student_ratings_url
diff --git a/web/app/assets/javascripts/profile.js b/web/app/assets/javascripts/profile.js
index 7e42a4747..01ef7cd00 100644
--- a/web/app/assets/javascripts/profile.js
+++ b/web/app/assets/javascripts/profile.js
@@ -1,985 +1,1007 @@
(function (context, $) {
- "use strict";
-
- context.JK = context.JK || {};
- context.JK.ProfileScreen = function (app) {
- var logger = context.JK.logger;
- var userId;
- var user = null;
- var userDefer = null;
- var rest = context.JK.Rest();
- var decrementedFriendCountOnce = false;
- var sentFriendRequest = false;
- var textMessageDialog = null;
- var feed = null;
- var player = null;
- var profileUtils = context.JK.ProfileUtils;
-
- var NOT_SPECIFIED_TEXT = 'Not specified';
-
- var $screen = $('#user-profile');
-
- var $biography = $screen.find('#biography');
-
- // musical experience
- var $instruments = $screen.find('.instruments-holder');
- var $musicianStatus = $screen.find('#musician-status');
- var $genres = $screen.find('#genres');
- var $concertCount = $screen.find('#concert-count');
- var $studioCount = $screen.find('#studio-count');
-
- // performance samples
- var $noSamples = $screen.find('.no-samples');
- var $jamkazamSamples = $screen.find('.jamkazam-samples');
- var $soundCloudSamples = $screen.find('.soundcloud-samples');
- var $youTubeSamples = $screen.find('.youtube-samples');
-
- // online presence
-
- var $userWebsite = $screen.find('.user-website');
- var $soundCloudPresence = $screen.find('.soundcloud-presence');
- var $reverbNationPresence = $screen.find('.reverbnation-presence');
- var $bandCampPresence = $screen.find('.bandcamp-presence');
- var $fandalismPresence = $screen.find('.fandalism-presence');
- var $youTubePresence = $screen.find('.youtube-presence');
- var $facebookPresence = $screen.find('.facebook-presence');
- var $twitterPresence = $screen.find('.twitter-presence');
-
- // current interests
- var $noInterests = $screen.find('#no-interests');
- var $paidGigSection = $screen.find('#paid-gigs');
- var $paidGigDetails = $screen.find('#paid-gig-details');
-
- var $freeGigSection = $screen.find('#free-gigs');
- var $freeGigDetails = $screen.find('#free-gig-details');
-
- var $cowritingSection = $screen.find('#cowriting');
- var $cowritingDetails = $screen.find('#cowriting-details');
-
- var $traditionalBandSection = $screen.find('#traditional-band');
- var $traditionalBandDetails = $screen.find('#traditional-band-details');
-
- var $virtualBandSection = $screen.find('#virtual-band');
- var $virtualBandDetails = $screen.find('#virtual-band-details');
-
- // tabs
- var $aboutLink = $screen.find('#about-link');
- var $aboutContent = $screen.find('#about-content');
-
- var $historyLink = $screen.find('#history-link');
- var $historyContent = $screen.find('#history-content');
-
- var $bandsLink = $screen.find('#bands-link');
- var $bandsContent = $screen.find('#bands-content');
-
- var $socialLink = $screen.find('#social-link');
- var $socialContent = $screen.find('#social-content');
-
- var $favoritesLink = $screen.find('#favorites-link');
- var $favoritesContent = $screen.find('#favorites-content');
-
- // stats
- var $friendStats = $screen.find('#friend-stats');
- var $followerStats = $screen.find('#follower-stats');
- var $sessionStats = $screen.find('#session-stats');
- var $recordingStats = $screen.find('#recording-stats');
- var $followingStats = $screen.find('#following-stats');
- var $favoriteStats = $screen.find('#favorite-stats');
-
- // miscellaneous
- var $userName = $screen.find('#username');
- var $avatar = $screen.find('#avatar');
- var $typeLabel = $screen.find('#type-label');
- var $location = $screen.find('#location');
- var $age = $screen.find('#age');
-
- // buttons
- var $profileActions = $screen.find('.profile-actions')
- var $btnEdit = $screen.find('.edit-profile-btn');
- var $btnTeacherProfileEdit = $screen.find('.edit-teacher-profile-btn');
- var $btnTeacherProfileView = $screen.find('.view-teacher-profile-btn');
- var $btnAddFriend = $screen.find('#btn-add-friend');
- var $btnFollowUser = $screen.find('#btn-follow-user');
- var $btnMessageUser = $screen.find('#btn-message-user');
- var $btnEditBio = $screen.find(".add-bio");
- var $btnAddRecordings = $screen.find('.add-recordings');
- var $btnAddSites = $screen.find('.add-sites');
- var $btnAddInterests = $screen.find('.add-interests');
- var $btnAddExperiences = $screen.find('.add-experiences')
-
- // social
- var $socialLeft = $screen.find('.profile-social-left');
- var $socialFriends = $screen.find('#social-friends');
- var $socialFollowings = $screen.find('#social-followings');
- var $socialFollowers = $screen.find('#social-followers');
-
- var instrument_logo_map = context.JK.getInstrumentIconMap24();
-
- function beforeShow(data) {
- userId = data.id;
- feed.setUser(userId);
- }
-
- function afterShow(data) {
- initUser();
- resetForm();
- renderAllStats();
- }
-
- function beforeHide(data) {
- feed.setUser(null);
- }
-
- function resetForm() {
- //$instruments.empty();
-
- $aboutContent.show();
- $historyContent.hide();
- $bandsContent.hide();
- $socialContent.hide();
- $favoritesContent.hide();
-
- $('.profile-nav a.active').removeClass('active');
- $aboutLink.addClass('active');
- }
-
- function initUser() {
- user = null;
- decrementedFriendCountOnce = false;
- sentFriendRequest = false;
- userDefer = rest.getUserProfile({id: userId, show_teacher:true})
- .done(function (response) {
- user = response;
- configureUserType();
- renderActive();
- renderAllStats();
- })
- .fail(function (jqXHR) {
- if (jqXHR.status >= 500) {
- context.JK.fetchUserNetworkOrServerFailure();
- }
- else if (jqXHR.status == 404) {
- context.JK.entityNotFound("User");
- }
- else {
- app.ajaxError(arguments);
- }
- });
- }
-
- function isMusician() {
- return user.musician;
- }
-
- function isTeacher() {
- return user.teacher;
- }
-
- function isCurrentUser() {
- return userId === context.JK.currentUserId;
- }
-
- function configureUserType() {
- if (isMusician()) {
- $historyLink.show();
- $bandsLink.show();
- $instruments.show();
- $sessionStats.show();
- $recordingStats.show();
- // $followingStats.hide();
- // $favoriteStats.hide();
- $socialLeft.show();
- $typeLabel.text('musician');
- $location.text('Location');
- } else {
- $historyLink.hide();
- $bandsLink.hide();
- $instruments.hide();
- $sessionStats.hide();
- $recordingStats.hide();
- // $followingStats.show();
- // $favoriteStats.show();
- $socialLeft.hide();
- $typeLabel.text('fan');
- $location.text('Presence');
- }
-
- if (isCurrentUser()) {
- $profileActions.show()
- $btnEdit.show();
- $btnTeacherProfileEdit.show();
- if(isTeacher()) {
- $btnTeacherProfileView.show();
- }
- else {
- $btnTeacherProfileView.hide();
- }
- $btnAddFriend.hide();
- $btnFollowUser.hide();
- $btnMessageUser.hide();
- } else {
- configureFriendFollowersControls();
-
- $profileActions.hide();
- $btnEdit.hide();
- $btnTeacherProfileEdit.hide();
- $btnTeacherProfileView.show();
- $btnAddFriend.show();
- $btnFollowUser.show();
- $btnMessageUser.show();
- }
- }
-
- function configureFriendFollowersControls() {
- // wire up Add Friend click
- configureFriendButton();
-
- // wire up Follow click
- configureFollowingButton();
- }
-
- /****************** MAIN PORTION OF SCREEN *****************/
- // events for main screen
- function events() {
- // wire up panel clicks -- these need to check deferred because they can't be hidden when in an invalid state
- $aboutLink.click(function () {
- renderTabDeferred(renderAbout)
- });
-
- $historyLink.click(function () {
- renderTabDeferred(renderHistory)
- });
-
- $bandsLink.click(function () {
- renderTabDeferred(renderBands)
- });
-
- $socialLink.click(function () {
- renderTabDeferred(renderSocial)
- });
-
- $favoritesLink.click(function () {
- renderTabDeferred(renderFavorites)
- });
-
- // this doesn't need deferred because it's only shown when valid
- $btnAddFriend.click(handleFriendChange);
- $btnFollowUser.click(handleFollowingChange);
- $btnMessageUser.click(handleMessageMusician);
-
- // Hook up soundcloud player:
- $soundCloudSamples.off("click", "a.sound-cloud-playable") .on("click", "a.sound-cloud-playable", playSoundCloudFile)
-
- $btnEdit.click(function(e) {
- e.preventDefault()
- window.ProfileActions.startProfileEdit(null, false)
- return false;
- })
- $btnTeacherProfileEdit.click(function(e) {
- e.preventDefault()
- window.ProfileActions.startTeacherEdit(null, false)
- return false;
- })
- $btnTeacherProfileView.click(function(e) {
- e.preventDefault()
- context.location = '/client#/profile/teacher/' + context.JK.currentUserId;
- return false;
- })
- $btnEditBio.click(function(e) {
- e.preventDefault()
- window.ProfileActions.startProfileEdit(null, true)
- return false;
- })
- $btnAddRecordings.click(function(e) {
- e.preventDefault()
- window.ProfileActions.startProfileEdit('samples', true)
- return false;
- })
- $btnAddSites.click(function(e) {
- e.preventDefault()
- window.ProfileActions.startProfileEdit('samples', true)
- return false;
- })
- $btnAddInterests.click(function(e) {
- e.preventDefault()
- window.ProfileActions.startProfileEdit('interests', true)
- return false;
- });
- $btnAddExperiences.click(function(e) {
- e.preventDefault()
- window.ProfileActions.startProfileEdit('experience', true)
- return false;
- })
- }
-
- function playSoundCloudFile(e) {
- e.preventDefault();
- var url = $(this).attr("soundcloud_url")
- var cap = $(this).text()
- player.initialize(url, cap);
- app.layout.showDialog('sound-cloud-player-dialog');
- return false;
- }
-
- function handleFriendChange(evt) {
- if (isFriend()) {
- removeFriend(evt);
- } else {
- sendFriendRequest(evt);
- }
- return false;
- }
-
- function handleFollowingChange(evt) {
- if (isFollowing()) {
- removeFollowing(false, userId);
- } else {
- addFollowing();
- }
- return false;
- }
-
- function handleMessageMusician(evt) {
- app.layout.showDialog('text-message', { d1: userId });
- return false;
- }
-
- function sendFriendRequest(evt) {
- evt.stopPropagation();
- setFriend(true); // TODO: you aren't a friend yet. just a request to be one really there are 3 states here.
- sentFriendRequest = true;
- rest.sendFriendRequest(app, userId, friendRequestCallback);
- }
-
- function removeFriend(evt) {
- evt.stopPropagation();
-
- rest.removeFriend({friend_id: userId})
- .done(function () {
- updateFriendCount(-1);
- setFriend(false);
- configureFriendButton();
- })
- .fail(app.ajaxError);
- }
-
- function isFriend() {
- return user.is_friend;
- }
-
- function setFriend(isFriend) {
- user.is_friend = isFriend;
- }
-
- function friendRequestCallback() {
- configureFriendButton();
- }
-
- function configureFriendButton() {
- if (isFriend()) {
- $btnAddFriend.text('DISCONNECT');
- } else {
- $btnAddFriend.text('CONNECT');
- }
- }
-
- function addFollowing() {
-
- rest.addFollowing({user_id: userId})
- .done(function () {
- updateFollowingCount(1);
- setFollowing(true);
- configureFollowingButton();
- context.JK.GA.trackJKSocial(context.JK.GA.Categories.jkFollow, isMusician() ? context.JK.GA.JKSocialTargets.musician : context.JK.GA.JKSocialTargets.fan);
- })
- .fail(app.ajaxError);
- }
-
- function removeFollowing(isBand, id) {
- rest.removeFollowing(id)
- .done(function () {
- if (!isBand) {
- updateFollowingCount(-1);
- setFollowing(false);
- configureFollowingButton();
- }
- else {
- updateBandFollowingCount(id, -1); // refresh stats
- configureBandFollowingButton(false, id);
- }
- })
- .fail(app.ajaxError);
- }
-
- function isFollowing() {
- return user.is_following;
- }
-
- function setFollowing(isFollowing) {
- user.is_following = isFollowing;
- }
-
- function configureFollowingButton() {
-
- if (isFollowing()) {
- $btnFollowUser.text('UNFOLLOW');
- } else {
- $btnFollowUser.text('FOLLOW');
- }
- }
-
- function configureEditProfileButton() {
- $btnFollowUser.click(addFollowing);
- }
-
- // refreshes the currently active tab
- function renderActive() {
- if ($aboutLink.hasClass('active')) {
- renderAbout();
- }
- else if ($historyLink.hasClass('active')) {
- renderHistory();
- }
- else if ($bandsLink.hasClass('active')) {
- renderBands();
- }
- else if ($socialLink.hasClass('active')) {
- renderSocial();
- }
- else if ($favoritesLink.hasClass('active')) {
- renderFavorites();
- }
- }
-
- function renderTabDeferred(tabRenderer) {
- userDefer
- .done(function () {
- tabRenderer();
- })
- .fail(function () {
- // try again
- initUser();
- })
- }
-
- function hideElements(elements) {
- $.each(elements, function(index, val) {
- val.hide();
- });
- }
-
- /****************** ABOUT TAB *****************/
- function renderAbout() {
- //$instruments.empty();
-
- $aboutContent.show();
- $historyContent.hide();
- $bandsContent.hide();
- $socialContent.hide();
- $favoritesContent.hide();
-
- $('.profile-nav a.active').removeClass('active');
- $aboutLink.addClass('active');
- }
-
- function renderAllStats() {
-
- if (!isCurrentUser()) {
- $btnEditBio.hide();
- $btnAddRecordings.hide();
- $btnAddSites.hide();
- $btnAddInterests.hide();
- }
-
- if (user && $userName) {
- renderNameLocationStats();
- renderBio();
- renderMusicalExperience();
- renderPerformanceSamples();
- renderOnlinePresence();
- renderInterests();
- }
- }
-
- function renderNameLocationStats() {
- // name
- $userName.html(user.name);
-
- // avatar
- $avatar.attr('src', context.JK.resolveAvatarUrl(user.photo_url));
-
- // location
- $location.html(user.location);
-
- $age.html(user.age ? user.age + " years old" : "");
+ "use strict";
+
+ context.JK = context.JK || {};
+ context.JK.ProfileScreen = function (app) {
+ var logger = context.JK.logger;
+ var userId;
+ var user = null;
+ var userDefer = null;
+ var rest = context.JK.Rest();
+ var decrementedFriendCountOnce = false;
+ var sentFriendRequest = false;
+ var textMessageDialog = null;
+ var feed = null;
+ var player = null;
+ var profileUtils = context.JK.ProfileUtils;
+ var EVENTS = context.JK.EVENTS;
+
+ var NOT_SPECIFIED_TEXT = 'Not specified';
+
+ var $screen = $('#user-profile');
+
+ var $biography = $screen.find('#biography');
+
+ // musical experience
+ var $instruments = $screen.find('.instruments-holder');
+ var $musicianStatus = $screen.find('#musician-status');
+ var $genres = $screen.find('#genres');
+ var $concertCount = $screen.find('#concert-count');
+ var $studioCount = $screen.find('#studio-count');
+
+ // performance samples
+ var $noSamples = $screen.find('.no-samples');
+ var $jamkazamSamples = $screen.find('.jamkazam-samples');
+ var $soundCloudSamples = $screen.find('.soundcloud-samples');
+ var $youTubeSamples = $screen.find('.youtube-samples');
+
+ // online presence
+
+ var $userWebsite = $screen.find('.user-website');
+ var $soundCloudPresence = $screen.find('.soundcloud-presence');
+ var $reverbNationPresence = $screen.find('.reverbnation-presence');
+ var $bandCampPresence = $screen.find('.bandcamp-presence');
+ var $fandalismPresence = $screen.find('.fandalism-presence');
+ var $youTubePresence = $screen.find('.youtube-presence');
+ var $facebookPresence = $screen.find('.facebook-presence');
+ var $twitterPresence = $screen.find('.twitter-presence');
+
+ // current interests
+ var $noInterests = $screen.find('#no-interests');
+ var $paidGigSection = $screen.find('#paid-gigs');
+ var $paidGigDetails = $screen.find('#paid-gig-details');
+
+ var $freeGigSection = $screen.find('#free-gigs');
+ var $freeGigDetails = $screen.find('#free-gig-details');
+
+ var $cowritingSection = $screen.find('#cowriting');
+ var $cowritingDetails = $screen.find('#cowriting-details');
+
+ var $traditionalBandSection = $screen.find('#traditional-band');
+ var $traditionalBandDetails = $screen.find('#traditional-band-details');
+
+ var $virtualBandSection = $screen.find('#virtual-band');
+ var $virtualBandDetails = $screen.find('#virtual-band-details');
+
+ // tabs
+ var $aboutLink = $screen.find('#about-link');
+ var $aboutContent = $screen.find('#about-content');
+
+ var $historyLink = $screen.find('#history-link');
+ var $historyContent = $screen.find('#history-content');
+
+ var $bandsLink = $screen.find('#bands-link');
+ var $bandsContent = $screen.find('#bands-content');
+
+ var $socialLink = $screen.find('#social-link');
+ var $socialContent = $screen.find('#social-content');
+
+ var $favoritesLink = $screen.find('#favorites-link');
+ var $favoritesContent = $screen.find('#favorites-content');
// stats
- var text = user.friend_count > 1 || user.friend_count === 0 ? " Friends" : " Friend";
- $friendStats.html('' + user.friend_count + '' + text);
+ var $friendStats = $screen.find('#friend-stats');
+ var $followerStats = $screen.find('#follower-stats');
+ var $sessionStats = $screen.find('#session-stats');
+ var $recordingStats = $screen.find('#recording-stats');
+ var $followingStats = $screen.find('#following-stats');
+ var $favoriteStats = $screen.find('#favorite-stats');
- text = user.follower_count > 1 || user.follower_count === 0 ? " Followers" : " Follower";
- $followerStats.html('' + user.follower_count + '' + text);
+ // miscellaneous
+ var $userName = $screen.find('#username');
+ var $avatar = $screen.find('#avatar');
+ var $typeLabel = $screen.find('#type-label');
+ var $location = $screen.find('#location');
+ var $age = $screen.find('#age');
- if (isMusician()) {
- text = user.session_count > 1 || user.session_count === 0 ? " Sessions" : " Session";
- $sessionStats.html(user.session_count + text);
+ // buttons
+ var $profileActions = $screen.find('.profile-actions')
+ var $btnEdit = $screen.find('.edit-profile-btn');
+ var $btnTeacherProfileEdit = $screen.find('.edit-teacher-profile-btn');
+ var $btnTeacherProfileView = $screen.find('.view-teacher-profile-btn');
+ var $btnAddFriend = $screen.find('#btn-add-friend');
+ var $btnFollowUser = $screen.find('#btn-follow-user');
+ var $btnMessageUser = $screen.find('#btn-message-user');
+ var $btnEditBio = $screen.find(".add-bio");
+ var $btnAddRecordings = $screen.find('.add-recordings');
+ var $btnAddSites = $screen.find('.add-sites');
+ var $btnAddInterests = $screen.find('.add-interests');
+ var $btnAddExperiences = $screen.find('.add-experiences')
- text = user.recording_count > 1 || user.recording_count === 0 ? " Recordings" : " Recording";
- $recordingStats.html(user.recording_count + text);
- } else {
- text = " Following";
- $followingStats.html(user.following_count + text);
- text = user.favorite_count > 1 || user.favorite_count === 0 ? " Favorites" : " Favorite";
- $favoriteStats.html(user.favorite_count + text);
- }
- }
+ // social
+ var $socialLeft = $screen.find('.profile-social-left');
+ var $socialFriends = $screen.find('#social-friends');
+ var $socialFollowings = $screen.find('#social-followings');
+ var $socialFollowers = $screen.find('#social-followers');
- function renderBio() {
- $biography.html(user.biography ? user.biography : NOT_SPECIFIED_TEXT);
- if (isCurrentUser()) {
- $btnEditBio.show();
- } else {
- $btnEditBio.hide();
- }
- }
+ var instrument_logo_map = context.JK.getInstrumentIconMap24();
- function renderMusicalExperience() {
- profileUtils.renderMusicalExperience(user, $screen, isCurrentUser())
- }
-
- function renderPerformanceSamples() {
- profileUtils.renderPerformanceSamples(user, $screen, isCurrentUser())
- }
-
- function renderOnlinePresence() {
- profileUtils.renderOnlinePresence(user, $screen, isCurrentUser())
- }
-
- function renderInterests() {
- // current interests
- if (isCurrentUser()) {
- $btnAddInterests.show();
- }
- else {
- $btnAddInterests.hide();
+ function beforeShow(data) {
+ userId = data.id;
+ feed.setUser(userId);
}
- var noInterests = !user.paid_sessions && !user.free_sessions && !user.cowriting && !user.virtual_band && !user.traditional_band;
- if (noInterests) {
- $noInterests.show();
- $paidGigSection.hide();
- $freeGigSection.hide();
- $cowritingSection.hide();
- $traditionalBandSection.hide();
- $virtualBandSection.hide();
- } else {
- $noInterests.hide();
+ function afterShow(data) {
+ initUser();
+ resetForm();
+ renderAllStats();
- // paid sessions
- if (user.paid_sessions) {
- $paidGigSection.show();
+ autoShowRatingDialogIfNeeded();
+ }
- var genreList = profileUtils.paidSessionGenreList(user.genres);
- $paidGigDetails.find("ul").html("");
- $paidGigDetails.find("ul").append('
Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
+ function autoShowRatingDialogIfNeeded() {
- var hourlyRate = user.paid_sessions_hourly_rate;
- $paidGigDetails.find("ul").append('Hourly rate = ' + (hourlyRate ? hourlyRate : NOT_SPECIFIED_TEXT) + '');
+ if ($.QueryString['selected']) {
+ var rewrite = true
+ app.layout.showDialog('rate-user-dialog', {d1: "student_" + userId}).one(EVENTS.DIALOG_CLOSED, function (e, data) {
+ if (!data.canceled) {
- var dailyRate = user.paid_sessions_daily_rate;
- $paidGigDetails.find("ul").append('Day rate = ' + (dailyRate ? dailyRate : NOT_SPECIFIED_TEXT) + '');
+ }
+ })
+ }
+
+ if (rewrite) {
+ if (window.history.replaceState) {//ie9 proofing
+ window.history.replaceState({}, "", "/client#/profile/teacher/#{e.id}")
+ }
+ }
+ }
+
+ function beforeHide(data) {
+ feed.setUser(null);
+ }
+
+ function resetForm() {
+ //$instruments.empty();
+
+ $aboutContent.show();
+ $historyContent.hide();
+ $bandsContent.hide();
+ $socialContent.hide();
+ $favoritesContent.hide();
+
+ $('.profile-nav a.active').removeClass('active');
+ $aboutLink.addClass('active');
+ }
+
+ function initUser() {
+ user = null;
+ decrementedFriendCountOnce = false;
+ sentFriendRequest = false;
+ userDefer = rest.getUserProfile({id: userId, show_teacher: true})
+ .done(function (response) {
+ user = response;
+ configureUserType();
+ renderActive();
+ renderAllStats();
+ })
+ .fail(function (jqXHR) {
+ if (jqXHR.status >= 500) {
+ context.JK.fetchUserNetworkOrServerFailure();
+ }
+ else if (jqXHR.status == 404) {
+ context.JK.entityNotFound("User");
+ }
+ else {
+ app.ajaxError(arguments);
+ }
+ });
+ }
+
+ function isMusician() {
+ return user.musician;
+ }
+
+ function isTeacher() {
+ return user.teacher;
+ }
+
+ function isCurrentUser() {
+ return userId === context.JK.currentUserId;
+ }
+
+ function configureUserType() {
+ if (isMusician()) {
+ $historyLink.show();
+ $bandsLink.show();
+ $instruments.show();
+ $sessionStats.show();
+ $recordingStats.show();
+ // $followingStats.hide();
+ // $favoriteStats.hide();
+ $socialLeft.show();
+ $typeLabel.text('musician');
+ $location.text('Location');
} else {
+ $historyLink.hide();
+ $bandsLink.hide();
+ $instruments.hide();
+ $sessionStats.hide();
+ $recordingStats.hide();
+ // $followingStats.show();
+ // $favoriteStats.show();
+ $socialLeft.hide();
+ $typeLabel.text('fan');
+ $location.text('Presence');
+ }
+
+ if (isCurrentUser()) {
+ $profileActions.show()
+ $btnEdit.show();
+ $btnTeacherProfileEdit.show();
+ if (isTeacher()) {
+ $btnTeacherProfileView.show();
+ }
+ else {
+ $btnTeacherProfileView.hide();
+ }
+ $btnAddFriend.hide();
+ $btnFollowUser.hide();
+ $btnMessageUser.hide();
+ } else {
+ configureFriendFollowersControls();
+
+ $profileActions.hide();
+ $btnEdit.hide();
+ $btnTeacherProfileEdit.hide();
+ $btnTeacherProfileView.show();
+ $btnAddFriend.show();
+ $btnFollowUser.show();
+ $btnMessageUser.show();
+ }
+ }
+
+ function configureFriendFollowersControls() {
+ // wire up Add Friend click
+ configureFriendButton();
+
+ // wire up Follow click
+ configureFollowingButton();
+ }
+
+ /****************** MAIN PORTION OF SCREEN *****************/
+ // events for main screen
+ function events() {
+ // wire up panel clicks -- these need to check deferred because they can't be hidden when in an invalid state
+ $aboutLink.click(function () {
+ renderTabDeferred(renderAbout)
+ });
+
+ $historyLink.click(function () {
+ renderTabDeferred(renderHistory)
+ });
+
+ $bandsLink.click(function () {
+ renderTabDeferred(renderBands)
+ });
+
+ $socialLink.click(function () {
+ renderTabDeferred(renderSocial)
+ });
+
+ $favoritesLink.click(function () {
+ renderTabDeferred(renderFavorites)
+ });
+
+ // this doesn't need deferred because it's only shown when valid
+ $btnAddFriend.click(handleFriendChange);
+ $btnFollowUser.click(handleFollowingChange);
+ $btnMessageUser.click(handleMessageMusician);
+
+ // Hook up soundcloud player:
+ $soundCloudSamples.off("click", "a.sound-cloud-playable").on("click", "a.sound-cloud-playable", playSoundCloudFile)
+
+ $btnEdit.click(function (e) {
+ e.preventDefault()
+ window.ProfileActions.startProfileEdit(null, false)
+ return false;
+ })
+ $btnTeacherProfileEdit.click(function (e) {
+ e.preventDefault()
+ window.ProfileActions.startTeacherEdit(null, false)
+ return false;
+ })
+ $btnTeacherProfileView.click(function (e) {
+ e.preventDefault()
+ context.location = '/client#/profile/teacher/' + context.JK.currentUserId;
+ return false;
+ })
+ $btnEditBio.click(function (e) {
+ e.preventDefault()
+ window.ProfileActions.startProfileEdit(null, true)
+ return false;
+ })
+ $btnAddRecordings.click(function (e) {
+ e.preventDefault()
+ window.ProfileActions.startProfileEdit('samples', true)
+ return false;
+ })
+ $btnAddSites.click(function (e) {
+ e.preventDefault()
+ window.ProfileActions.startProfileEdit('samples', true)
+ return false;
+ })
+ $btnAddInterests.click(function (e) {
+ e.preventDefault()
+ window.ProfileActions.startProfileEdit('interests', true)
+ return false;
+ });
+ $btnAddExperiences.click(function (e) {
+ e.preventDefault()
+ window.ProfileActions.startProfileEdit('experience', true)
+ return false;
+ })
+ }
+
+ function playSoundCloudFile(e) {
+ e.preventDefault();
+ var url = $(this).attr("soundcloud_url")
+ var cap = $(this).text()
+ player.initialize(url, cap);
+ app.layout.showDialog('sound-cloud-player-dialog');
+ return false;
+ }
+
+ function handleFriendChange(evt) {
+ if (isFriend()) {
+ removeFriend(evt);
+ } else {
+ sendFriendRequest(evt);
+ }
+ return false;
+ }
+
+ function handleFollowingChange(evt) {
+ if (isFollowing()) {
+ removeFollowing(false, userId);
+ } else {
+ addFollowing();
+ }
+ return false;
+ }
+
+ function handleMessageMusician(evt) {
+ app.layout.showDialog('text-message', {d1: userId});
+ return false;
+ }
+
+ function sendFriendRequest(evt) {
+ evt.stopPropagation();
+ setFriend(true); // TODO: you aren't a friend yet. just a request to be one really there are 3 states here.
+ sentFriendRequest = true;
+ rest.sendFriendRequest(app, userId, friendRequestCallback);
+ }
+
+ function removeFriend(evt) {
+ evt.stopPropagation();
+
+ rest.removeFriend({friend_id: userId})
+ .done(function () {
+ updateFriendCount(-1);
+ setFriend(false);
+ configureFriendButton();
+ })
+ .fail(app.ajaxError);
+ }
+
+ function isFriend() {
+ return user.is_friend;
+ }
+
+ function setFriend(isFriend) {
+ user.is_friend = isFriend;
+ }
+
+ function friendRequestCallback() {
+ configureFriendButton();
+ }
+
+ function configureFriendButton() {
+ if (isFriend()) {
+ $btnAddFriend.text('DISCONNECT');
+ } else {
+ $btnAddFriend.text('CONNECT');
+ }
+ }
+
+ function addFollowing() {
+
+ rest.addFollowing({user_id: userId})
+ .done(function () {
+ updateFollowingCount(1);
+ setFollowing(true);
+ configureFollowingButton();
+ context.JK.GA.trackJKSocial(context.JK.GA.Categories.jkFollow, isMusician() ? context.JK.GA.JKSocialTargets.musician : context.JK.GA.JKSocialTargets.fan);
+ })
+ .fail(app.ajaxError);
+ }
+
+ function removeFollowing(isBand, id) {
+ rest.removeFollowing(id)
+ .done(function () {
+ if (!isBand) {
+ updateFollowingCount(-1);
+ setFollowing(false);
+ configureFollowingButton();
+ }
+ else {
+ updateBandFollowingCount(id, -1); // refresh stats
+ configureBandFollowingButton(false, id);
+ }
+ })
+ .fail(app.ajaxError);
+ }
+
+ function isFollowing() {
+ return user.is_following;
+ }
+
+ function setFollowing(isFollowing) {
+ user.is_following = isFollowing;
+ }
+
+ function configureFollowingButton() {
+
+ if (isFollowing()) {
+ $btnFollowUser.text('UNFOLLOW');
+ } else {
+ $btnFollowUser.text('FOLLOW');
+ }
+ }
+
+ function configureEditProfileButton() {
+ $btnFollowUser.click(addFollowing);
+ }
+
+ // refreshes the currently active tab
+ function renderActive() {
+ if ($aboutLink.hasClass('active')) {
+ renderAbout();
+ }
+ else if ($historyLink.hasClass('active')) {
+ renderHistory();
+ }
+ else if ($bandsLink.hasClass('active')) {
+ renderBands();
+ }
+ else if ($socialLink.hasClass('active')) {
+ renderSocial();
+ }
+ else if ($favoritesLink.hasClass('active')) {
+ renderFavorites();
+ }
+ }
+
+ function renderTabDeferred(tabRenderer) {
+ userDefer
+ .done(function () {
+ tabRenderer();
+ })
+ .fail(function () {
+ // try again
+ initUser();
+ })
+ }
+
+ function hideElements(elements) {
+ $.each(elements, function (index, val) {
+ val.hide();
+ });
+ }
+
+ /****************** ABOUT TAB *****************/
+ function renderAbout() {
+ //$instruments.empty();
+
+ $aboutContent.show();
+ $historyContent.hide();
+ $bandsContent.hide();
+ $socialContent.hide();
+ $favoritesContent.hide();
+
+ $('.profile-nav a.active').removeClass('active');
+ $aboutLink.addClass('active');
+ }
+
+ function renderAllStats() {
+
+ if (!isCurrentUser()) {
+ $btnEditBio.hide();
+ $btnAddRecordings.hide();
+ $btnAddSites.hide();
+ $btnAddInterests.hide();
+ }
+
+ if (user && $userName) {
+ renderNameLocationStats();
+ renderBio();
+ renderMusicalExperience();
+ renderPerformanceSamples();
+ renderOnlinePresence();
+ renderInterests();
+ }
+ }
+
+ function renderNameLocationStats() {
+ // name
+ $userName.html(user.name);
+
+ // avatar
+ $avatar.attr('src', context.JK.resolveAvatarUrl(user.photo_url));
+
+ // location
+ $location.html(user.location);
+
+ $age.html(user.age ? user.age + " years old" : "");
+
+ // stats
+ var text = user.friend_count > 1 || user.friend_count === 0 ? " Friends" : " Friend";
+ $friendStats.html('' + user.friend_count + '' + text);
+
+ text = user.follower_count > 1 || user.follower_count === 0 ? " Followers" : " Follower";
+ $followerStats.html('' + user.follower_count + '' + text);
+
+ if (isMusician()) {
+ text = user.session_count > 1 || user.session_count === 0 ? " Sessions" : " Session";
+ $sessionStats.html(user.session_count + text);
+
+ text = user.recording_count > 1 || user.recording_count === 0 ? " Recordings" : " Recording";
+ $recordingStats.html(user.recording_count + text);
+ } else {
+ text = " Following";
+ $followingStats.html(user.following_count + text);
+ text = user.favorite_count > 1 || user.favorite_count === 0 ? " Favorites" : " Favorite";
+ $favoriteStats.html(user.favorite_count + text);
+ }
+ }
+
+ function renderBio() {
+ $biography.html(user.biography ? user.biography : NOT_SPECIFIED_TEXT);
+ if (isCurrentUser()) {
+ $btnEditBio.show();
+ } else {
+ $btnEditBio.hide();
+ }
+ }
+
+ function renderMusicalExperience() {
+ profileUtils.renderMusicalExperience(user, $screen, isCurrentUser())
+ }
+
+ function renderPerformanceSamples() {
+ profileUtils.renderPerformanceSamples(user, $screen, isCurrentUser())
+ }
+
+ function renderOnlinePresence() {
+ profileUtils.renderOnlinePresence(user, $screen, isCurrentUser())
+ }
+
+ function renderInterests() {
+ // current interests
+ if (isCurrentUser()) {
+ $btnAddInterests.show();
+ }
+ else {
+ $btnAddInterests.hide();
+ }
+
+ var noInterests = !user.paid_sessions && !user.free_sessions && !user.cowriting && !user.virtual_band && !user.traditional_band;
+ if (noInterests) {
+ $noInterests.show();
$paidGigSection.hide();
- }
-
- // free sessions
- if (user.free_sessions) {
- $freeGigSection.show();
- $freeGigDetails.find("ul").html("");
- var genreList = profileUtils.freeSessionGenreList(user.genres);
- $freeGigDetails.find("ul").append('Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
- } else {
$freeGigSection.hide();
- }
-
- // cowriting
- if (user.cowriting) {
- $cowritingSection.show();
- $cowritingDetails.find("ul").html("");
- var genreList = profileUtils.cowritingGenreList(user.genres);
- $cowritingDetails.find("ul").append('Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
-
- var purpose = user.cowriting_purpose;
- $cowritingDetails.find("ul").append('Purpose: ' + (purpose ? profileUtils.cowritingPurposeMap[purpose] : NOT_SPECIFIED_TEXT) + '');
- } else {
$cowritingSection.hide();
- }
-
- // traditional bands
- if (user.traditional_band) {
- $traditionalBandSection.show();
- $traditionalBandDetails.find("ul").html("");
- var genreList = profileUtils.traditionalBandGenreList(user.genres);
- $traditionalBandDetails.find("ul").append('Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
-
- var commitment = user.traditional_band_commitment;
- $traditionalBandDetails.find("ul").append('Commitment: ' + (commitment ? profileUtils.bandCommitmentMap[commitment] : NOT_SPECIFIED_TEXT) + '');
-
- var canTour = user.traditional_band_touring;
- var canTourResponse = canTour ? "Yes" : (canTour === false ? "No" : NOT_SPECIFIED_TEXT);
- $traditionalBandDetails.find("ul").append('Touring: ' + canTourResponse + '');
- } else {
$traditionalBandSection.hide();
- }
-
- // virtual band
- if (user.virtual_band) {
- $virtualBandSection.show();
- $virtualBandDetails.find("ul").html("");
- var genreList = profileUtils.virtualBandGenreList(user.genres);
- $virtualBandDetails.find("ul").append('Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
-
- var commitment = user.virtual_band_commitment;
- $virtualBandDetails.find("ul").append('Commitment: ' + (commitment ? profileUtils.bandCommitmentMap[commitment] : NOT_SPECIFIED_TEXT) + '');
- } else {
$virtualBandSection.hide();
+ } else {
+ $noInterests.hide();
+
+ // paid sessions
+ if (user.paid_sessions) {
+ $paidGigSection.show();
+
+ var genreList = profileUtils.paidSessionGenreList(user.genres);
+ $paidGigDetails.find("ul").html("");
+ $paidGigDetails.find("ul").append('Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
+
+ var hourlyRate = user.paid_sessions_hourly_rate;
+ $paidGigDetails.find("ul").append('Hourly rate = ' + (hourlyRate ? hourlyRate : NOT_SPECIFIED_TEXT) + '');
+
+ var dailyRate = user.paid_sessions_daily_rate;
+ $paidGigDetails.find("ul").append('Day rate = ' + (dailyRate ? dailyRate : NOT_SPECIFIED_TEXT) + '');
+ } else {
+ $paidGigSection.hide();
+ }
+
+ // free sessions
+ if (user.free_sessions) {
+ $freeGigSection.show();
+ $freeGigDetails.find("ul").html("");
+ var genreList = profileUtils.freeSessionGenreList(user.genres);
+ $freeGigDetails.find("ul").append('Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
+ } else {
+ $freeGigSection.hide();
+ }
+
+ // cowriting
+ if (user.cowriting) {
+ $cowritingSection.show();
+ $cowritingDetails.find("ul").html("");
+ var genreList = profileUtils.cowritingGenreList(user.genres);
+ $cowritingDetails.find("ul").append('Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
+
+ var purpose = user.cowriting_purpose;
+ $cowritingDetails.find("ul").append('Purpose: ' + (purpose ? profileUtils.cowritingPurposeMap[purpose] : NOT_SPECIFIED_TEXT) + '');
+ } else {
+ $cowritingSection.hide();
+ }
+
+ // traditional bands
+ if (user.traditional_band) {
+ $traditionalBandSection.show();
+ $traditionalBandDetails.find("ul").html("");
+ var genreList = profileUtils.traditionalBandGenreList(user.genres);
+ $traditionalBandDetails.find("ul").append('Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
+
+ var commitment = user.traditional_band_commitment;
+ $traditionalBandDetails.find("ul").append('Commitment: ' + (commitment ? profileUtils.bandCommitmentMap[commitment] : NOT_SPECIFIED_TEXT) + '');
+
+ var canTour = user.traditional_band_touring;
+ var canTourResponse = canTour ? "Yes" : (canTour === false ? "No" : NOT_SPECIFIED_TEXT);
+ $traditionalBandDetails.find("ul").append('Touring: ' + canTourResponse + '');
+ } else {
+ $traditionalBandSection.hide();
+ }
+
+ // virtual band
+ if (user.virtual_band) {
+ $virtualBandSection.show();
+ $virtualBandDetails.find("ul").html("");
+ var genreList = profileUtils.virtualBandGenreList(user.genres);
+ $virtualBandDetails.find("ul").append('Genre(s): ' + (genreList.length > 0 ? genreList : NOT_SPECIFIED_TEXT) + '');
+
+ var commitment = user.virtual_band_commitment;
+ $virtualBandDetails.find("ul").append('Commitment: ' + (commitment ? profileUtils.bandCommitmentMap[commitment] : NOT_SPECIFIED_TEXT) + '');
+ } else {
+ $virtualBandSection.hide();
+ }
}
}
- }
- /****************** SOCIAL TAB *****************/
- function renderSocial() {
- $socialFriends.empty();
- $socialFollowings.empty();
- $socialFollowers.empty();
+ /****************** SOCIAL TAB *****************/
+ function renderSocial() {
+ $socialFriends.empty();
+ $socialFollowings.empty();
+ $socialFollowers.empty();
- $aboutContent.hide();
- $historyContent.hide();
- $bandsContent.hide();
- $socialContent.show();
- $favoritesContent.hide();
+ $aboutContent.hide();
+ $historyContent.hide();
+ $bandsContent.hide();
+ $socialContent.show();
+ $favoritesContent.hide();
- $('.profile-nav a.active').removeClass('active');
- $socialLink.addClass('active');
+ $('.profile-nav a.active').removeClass('active');
+ $socialLink.addClass('active');
- bindSocial();
- }
+ bindSocial();
+ }
- function bindSocial() {
- if (isMusician()) {
- // FRIENDS
- rest.getFriends({id: userId})
+ function bindSocial() {
+ if (isMusician()) {
+ // FRIENDS
+ rest.getFriends({id: userId})
+ .done(function (response) {
+ if (response && response.length > 0) {
+ $.each(response, function (index, val) {
+ var template = $('#template-profile-social').html();
+ var friendHtml = context.JK.fillTemplate(template, {
+ userId: val.id,
+ hoverAttributeId: "user-id",
+ hoverAction: val.musician ? "musician" : "fan",
+ avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
+ userName: val.name,
+ location: val.location,
+ type: "Friends"
+ });
+
+ $socialFriends.append(friendHtml);
+ });
+ }
+ else {
+ $socialFriends.html(' ');
+ }
+ context.JK.bindHoverEvents();
+ })
+ .fail(app.ajaxError)
+ }
+
+ rest.getFollowings({id: userId})
.done(function (response) {
if (response && response.length > 0) {
$.each(response, function (index, val) {
var template = $('#template-profile-social').html();
- var friendHtml = context.JK.fillTemplate(template, {
+ var followingHtml = context.JK.fillTemplate(template, {
userId: val.id,
- hoverAttributeId: "user-id",
- hoverAction: val.musician ? "musician" : "fan",
+ hoverAttributeId: val.type === "user" ? "user-id" : "band-id",
+ hoverAction: val.type === "user" ? (val.musician ? "musician" : "fan") : "band",
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
userName: val.name,
- location: val.location,
- type: "Friends"
+ location: val.location
});
- $socialFriends.append(friendHtml);
+ $socialFollowings.append(followingHtml);
});
}
else {
- $socialFriends.html(' ');
+ $socialFollowings.html(' ');
}
context.JK.bindHoverEvents();
})
- .fail(app.ajaxError)
- }
+ .fail(app.ajaxError);
- rest.getFollowings({id: userId})
- .done(function (response) {
- if (response && response.length > 0) {
+ rest.getFollowers({id: userId})
+ .done(function (response) {
$.each(response, function (index, val) {
var template = $('#template-profile-social').html();
- var followingHtml = context.JK.fillTemplate(template, {
+ var followerHtml = context.JK.fillTemplate(template, {
userId: val.id,
- hoverAttributeId: val.type === "user" ? "user-id" : "band-id",
- hoverAction: val.type === "user" ? (val.musician ? "musician" : "fan") : "band",
+ hoverAttributeId: "user-id",
+ hoverAction: val.musician ? "musician" : "fan",
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
userName: val.name,
location: val.location
});
- $socialFollowings.append(followingHtml);
+ $socialFollowers.append(followerHtml);
});
- }
- else {
- $socialFollowings.html(' ');
- }
- context.JK.bindHoverEvents();
- })
- .fail(app.ajaxError);
-
- rest.getFollowers({id: userId})
- .done(function (response) {
- $.each(response, function (index, val) {
- var template = $('#template-profile-social').html();
- var followerHtml = context.JK.fillTemplate(template, {
- userId: val.id,
- hoverAttributeId: "user-id",
- hoverAction: val.musician ? "musician" : "fan",
- avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
- userName: val.name,
- location: val.location
- });
-
- $socialFollowers.append(followerHtml);
- });
- context.JK.bindHoverEvents();
- })
- .fail(app.ajaxError);
- }
-
- /****************** HISTORY TAB *****************/
- function renderHistory() {
- $aboutContent.hide();
- $historyContent.show();
- $bandsContent.hide();
- $socialContent.hide();
- $favoritesContent.hide();
-
- $('.profile-nav a.active').removeClass('active');
- $historyLink.addClass('active');
-
- bindHistory();
- }
-
- function bindHistory() {
- feed.refresh();
- }
-
- /****************** BANDS TAB *****************/
- function renderBands() {
- $bandsContent.empty();
-
- $aboutContent.hide();
- $historyContent.hide();
- $bandsContent.show();
- $socialContent.hide();
- $favoritesContent.hide();
-
- $('.profile-nav a.active').removeClass('active');
- $bandsLink.addClass('active');
-
- bindBands();
- }
-
- function bindBands() {
-
- rest.getBands({id: userId})
- .done(function (response) {
- if ((!response || response.length === 0) && isCurrentUser()) {
- var noBandHtml = $('#template-no-bands').html();
- $bandsContent.html(noBandHtml);
- }
- else {
- addMoreBandsLink();
-
- $.each(response, function (index, val) {
- var isBandMember = false;
-
- // build band member HTML
- var musicianHtml = '';
- if (val.musicians) {
- for (var i = 0; i < val.musicians.length; i++) {
- var musician = val.musicians[i];
- var instrumentLogoHtml = '';
- if (musician.instruments) {
- for (var j = 0; j < musician.instruments.length; j++) {
- var instrument = musician.instruments[j];
- var inst = '/assets/content/icon_instrument_default24.png';
- var toolTip = '';
- if (instrument.instrument_id in instrument_logo_map) {
- inst = instrument_logo_map[instrument.instrument_id].asset;
- toolTip = instrument.instrument_id;
- }
- instrumentLogoHtml += '
';
- }
- }
- if (!isBandMember)
- isBandMember = musician.id === context.JK.currentUserId;
-
- // this template is in _findSession.html.erb
- var musicianTemplate = $('#template-musician-info').html();
- musicianHtml += context.JK.fillTemplate(musicianTemplate, {
- userId: musician.id,
- avatar_url: context.JK.resolveAvatarUrl(musician.photo_url),
- profile_url: "/client#/profile/" + musician.id,
- musician_name: musician.name,
- instruments: instrumentLogoHtml,
- more_link: ''
- });
- }
- }
- var template = $('#template-profile-bands').html();
- var bandHtml = context.JK.fillTemplate(template, {
- bandId: val.id,
- biography: val.biography,
- profile_url: "/client#/bandProfile/" + val.id,
- band_edit_url: "/client#/band/setup/" + val.id + '/step0',
- band_member_url: "/client#/band/setup/" + val.id + '/step4',
- avatar_url: context.JK.resolveBandAvatarUrl(val.photo_url),
- name: val.name,
- location: val.location,
- genres: formatGenres(val.genres),
- follower_count: val.follower_count,
- recording_count: val.recording_count,
- session_count: val.session_count,
- musicians: musicianHtml
- });
-
- $bandsContent.append(bandHtml);
-
- $('.profile-band-link-member-true').each(function(idx) {
- isBandMember ? $(this).show() : $(this).hide();
- });
- $('.profile-band-link-member-false').each(function(idx) {
- isBandMember ? $(this).hide() : $(this).show();
- });
-
- // wire up Band Follow button click handler
- configureBandFollowingButton(val.is_following, val.id);
- });
-
- if (response.length >= 3) {
- addMoreBandsLink();
- }
- }
- context.JK.bindHoverEvents();
- })
- .fail(app.ajaxError);
- }
-
- function addMoreBandsLink() {
- if (isCurrentUser()) {
- var moreBandsHtml = $('#template-more-bands').html();
- $bandsContent.append(moreBandsHtml);
+ context.JK.bindHoverEvents();
+ })
+ .fail(app.ajaxError);
}
- }
- function formatGenres(genres) {
- var formattedGenres = '';
- if (genres) {
- for (var i = 0; i < genres.length; i++) {
- var genre = genres[i];
- formattedGenres += genre.description;
- if (i < genres.length - 1) {
- formattedGenres += ', ';
- }
+ /****************** HISTORY TAB *****************/
+ function renderHistory() {
+ $aboutContent.hide();
+ $historyContent.show();
+ $bandsContent.hide();
+ $socialContent.hide();
+ $favoritesContent.hide();
+
+ $('.profile-nav a.active').removeClass('active');
+ $historyLink.addClass('active');
+
+ bindHistory();
+ }
+
+ function bindHistory() {
+ feed.refresh();
+ }
+
+ /****************** BANDS TAB *****************/
+ function renderBands() {
+ $bandsContent.empty();
+
+ $aboutContent.hide();
+ $historyContent.hide();
+ $bandsContent.show();
+ $socialContent.hide();
+ $favoritesContent.hide();
+
+ $('.profile-nav a.active').removeClass('active');
+ $bandsLink.addClass('active');
+
+ bindBands();
+ }
+
+ function bindBands() {
+
+ rest.getBands({id: userId})
+ .done(function (response) {
+ if ((!response || response.length === 0) && isCurrentUser()) {
+ var noBandHtml = $('#template-no-bands').html();
+ $bandsContent.html(noBandHtml);
+ }
+ else {
+ addMoreBandsLink();
+
+ $.each(response, function (index, val) {
+ var isBandMember = false;
+
+ // build band member HTML
+ var musicianHtml = '';
+ if (val.musicians) {
+ for (var i = 0; i < val.musicians.length; i++) {
+ var musician = val.musicians[i];
+ var instrumentLogoHtml = '';
+ if (musician.instruments) {
+ for (var j = 0; j < musician.instruments.length; j++) {
+ var instrument = musician.instruments[j];
+ var inst = '/assets/content/icon_instrument_default24.png';
+ var toolTip = '';
+ if (instrument.instrument_id in instrument_logo_map) {
+ inst = instrument_logo_map[instrument.instrument_id].asset;
+ toolTip = instrument.instrument_id;
+ }
+ instrumentLogoHtml += '
';
+ }
+ }
+ if (!isBandMember)
+ isBandMember = musician.id === context.JK.currentUserId;
+
+ // this template is in _findSession.html.erb
+ var musicianTemplate = $('#template-musician-info').html();
+ musicianHtml += context.JK.fillTemplate(musicianTemplate, {
+ userId: musician.id,
+ avatar_url: context.JK.resolveAvatarUrl(musician.photo_url),
+ profile_url: "/client#/profile/" + musician.id,
+ musician_name: musician.name,
+ instruments: instrumentLogoHtml,
+ more_link: ''
+ });
+ }
+ }
+ var template = $('#template-profile-bands').html();
+ var bandHtml = context.JK.fillTemplate(template, {
+ bandId: val.id,
+ biography: val.biography,
+ profile_url: "/client#/bandProfile/" + val.id,
+ band_edit_url: "/client#/band/setup/" + val.id + '/step0',
+ band_member_url: "/client#/band/setup/" + val.id + '/step4',
+ avatar_url: context.JK.resolveBandAvatarUrl(val.photo_url),
+ name: val.name,
+ location: val.location,
+ genres: formatGenres(val.genres),
+ follower_count: val.follower_count,
+ recording_count: val.recording_count,
+ session_count: val.session_count,
+ musicians: musicianHtml
+ });
+
+ $bandsContent.append(bandHtml);
+
+ $('.profile-band-link-member-true').each(function (idx) {
+ isBandMember ? $(this).show() : $(this).hide();
+ });
+ $('.profile-band-link-member-false').each(function (idx) {
+ isBandMember ? $(this).hide() : $(this).show();
+ });
+
+ // wire up Band Follow button click handler
+ configureBandFollowingButton(val.is_following, val.id);
+ });
+
+ if (response.length >= 3) {
+ addMoreBandsLink();
+ }
+ }
+ context.JK.bindHoverEvents();
+ })
+ .fail(app.ajaxError);
+ }
+
+ function addMoreBandsLink() {
+ if (isCurrentUser()) {
+ var moreBandsHtml = $('#template-more-bands').html();
+ $bandsContent.append(moreBandsHtml);
}
}
- return formattedGenres;
- }
- function updateFriendCount(value) {
- if (!decrementedFriendCountOnce && !sentFriendRequest) {
- decrementedFriendCountOnce = true;
- var friendCount = $('#profile-friend-stats span.friend-count');
- friendCount.text(value + parseInt(friendCount.text()));
+ function formatGenres(genres) {
+ var formattedGenres = '';
+ if (genres) {
+ for (var i = 0; i < genres.length; i++) {
+ var genre = genres[i];
+ formattedGenres += genre.description;
+ if (i < genres.length - 1) {
+ formattedGenres += ', ';
+ }
+ }
+ }
+ return formattedGenres;
}
- }
- function updateFollowingCount(value) {
- var $followingCount = $('#follower-stats span.follower-count');
- $followingCount.text(value + parseInt($followingCount.text()));
- }
-
- function updateBandFollowingCount(bandId, value) {
- var $bandFollowing = $('div[band-id="' + bandId + '"].profile-bands span.follower-count');
- $bandFollowing.text(value + parseInt($bandFollowing.text()));
- }
-
- function addBandFollowing(evt) {
- evt.stopPropagation();
- var bandId = $(this).parent().parent().parent().parent().attr('band-id');
-
- var newFollowing = {};
- newFollowing.band_id = bandId;
-
- rest.addFollowing(newFollowing)
- .done(function (response) {
- updateBandFollowingCount(bandId, 1); // increase counter
- configureBandFollowingButton(true, bandId);
- context.JK.GA.trackJKSocial(context.JK.GA.Categories.jkFollow, context.JK.GA.JKSocialTargets.band);
- })
- .fail(app.ajaxError);
- }
-
- function configureBandFollowingButton(following, bandId) {
- var $btnFollowBand = $('div[band-id=' + bandId + ']', '#bands-content').find('#btn-follow-band');
- $btnFollowBand.unbind("click");
-
- if (following) {
- $btnFollowBand.text('UNFOLLOW');
- $btnFollowBand.click(function (evt) {
- removeFollowing(true, bandId);
- evt.stopPropagation();
- return false;
- });
- } else {
- $btnFollowBand.text('FOLLOW');
- $btnFollowBand.click(addBandFollowing);
+ function updateFriendCount(value) {
+ if (!decrementedFriendCountOnce && !sentFriendRequest) {
+ decrementedFriendCountOnce = true;
+ var friendCount = $('#profile-friend-stats span.friend-count');
+ friendCount.text(value + parseInt(friendCount.text()));
+ }
}
- }
- /****************** FAVORITES TAB *****************/
- function renderFavorites() {
- $aboutContent.hide();
- $historyContent.hide();
- $bandsContent.hide();
- $socialContent.hide();
- $favoritesContent.show();
+ function updateFollowingCount(value) {
+ var $followingCount = $('#follower-stats span.follower-count');
+ $followingCount.text(value + parseInt($followingCount.text()));
+ }
- $('.profile-nav a.active').removeClass('active');
- $favoritesLink.addClass('active');
+ function updateBandFollowingCount(bandId, value) {
+ var $bandFollowing = $('div[band-id="' + bandId + '"].profile-bands span.follower-count');
+ $bandFollowing.text(value + parseInt($bandFollowing.text()));
+ }
- bindFavorites();
- }
+ function addBandFollowing(evt) {
+ evt.stopPropagation();
+ var bandId = $(this).parent().parent().parent().parent().attr('band-id');
+
+ var newFollowing = {};
+ newFollowing.band_id = bandId;
+
+ rest.addFollowing(newFollowing)
+ .done(function (response) {
+ updateBandFollowingCount(bandId, 1); // increase counter
+ configureBandFollowingButton(true, bandId);
+ context.JK.GA.trackJKSocial(context.JK.GA.Categories.jkFollow, context.JK.GA.JKSocialTargets.band);
+ })
+ .fail(app.ajaxError);
+ }
+
+ function configureBandFollowingButton(following, bandId) {
+ var $btnFollowBand = $('div[band-id=' + bandId + ']', '#bands-content').find('#btn-follow-band');
+ $btnFollowBand.unbind("click");
+
+ if (following) {
+ $btnFollowBand.text('UNFOLLOW');
+ $btnFollowBand.click(function (evt) {
+ removeFollowing(true, bandId);
+ evt.stopPropagation();
+ return false;
+ });
+ } else {
+ $btnFollowBand.text('FOLLOW');
+ $btnFollowBand.click(addBandFollowing);
+ }
+ }
+
+ /****************** FAVORITES TAB *****************/
+ function renderFavorites() {
+ $aboutContent.hide();
+ $historyContent.hide();
+ $bandsContent.hide();
+ $socialContent.hide();
+ $favoritesContent.show();
+
+ $('.profile-nav a.active').removeClass('active');
+ $favoritesLink.addClass('active');
+
+ bindFavorites();
+ }
- function bindFavorites() {
- }
+ function bindFavorites() {
+ }
- function initializeFeed() {
+ function initializeFeed() {
- var $scroller = $screen.find('.content-body-scroller#user-profile-feed-scroller');
- var $content = $screen.find('.feed-content#user-profile-feed-entry-list');
- var $noMoreFeeds = $screen.find('#user-profile-end-of-feeds-list');
- var $refresh = $screen.find('.btn-refresh-entries');
- var $sortFeedBy = $screen.find('#feed_order_by');
- var $includeDate = $screen.find('#feed_date');
- var $includeType = $screen.find('#feed_show');
+ var $scroller = $screen.find('.content-body-scroller#user-profile-feed-scroller');
+ var $content = $screen.find('.feed-content#user-profile-feed-entry-list');
+ var $noMoreFeeds = $screen.find('#user-profile-end-of-feeds-list');
+ var $refresh = $screen.find('.btn-refresh-entries');
+ var $sortFeedBy = $screen.find('#feed_order_by');
+ var $includeDate = $screen.find('#feed_date');
+ var $includeType = $screen.find('#feed_show');
- feed = new context.JK.Feed(app);
- feed.initialize($screen, $scroller, $content, $noMoreFeeds, $refresh, $sortFeedBy, $includeDate, $includeType, {time_range: 'all'});
- }
+ feed = new context.JK.Feed(app);
+ feed.initialize($screen, $scroller, $content, $noMoreFeeds, $refresh, $sortFeedBy, $includeDate, $includeType, {time_range: 'all'});
+ }
- function initialize(textMessageDialogInstance) {
- textMessageDialog = textMessageDialogInstance;
- var screenBindings = {
- 'beforeShow': beforeShow,
- 'afterShow': afterShow,
- 'beforeHide' : beforeHide
- };
- app.bindScreen('profile', screenBindings);
- events();
- initializeFeed();
- player = new context.JK.SoundCloudPlayerDialog(app);
- }
+ function initialize(textMessageDialogInstance) {
+ textMessageDialog = textMessageDialogInstance;
+ var screenBindings = {
+ 'beforeShow': beforeShow,
+ 'afterShow': afterShow,
+ 'beforeHide': beforeHide
+ };
+ app.bindScreen('profile', screenBindings);
+ events();
+ initializeFeed();
+ player = new context.JK.SoundCloudPlayerDialog(app);
+ }
- this.initialize = initialize;
- this.beforeShow = beforeShow;
- this.afterShow = afterShow;
- return this;
- };
+ this.initialize = initialize;
+ this.beforeShow = beforeShow;
+ this.afterShow = afterShow;
+ return this;
+ };
-})(window, jQuery);
\ No newline at end of file
+ })
+(window, jQuery);
\ No newline at end of file
diff --git a/web/app/assets/javascripts/react-components/AccountPaymentHistoryScreen.js.jsx.coffee b/web/app/assets/javascripts/react-components/AccountPaymentHistoryScreen.js.jsx.coffee
index 13a6d8178..5bc85d3f4 100644
--- a/web/app/assets/javascripts/react-components/AccountPaymentHistoryScreen.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/AccountPaymentHistoryScreen.js.jsx.coffee
@@ -49,7 +49,6 @@ profileUtils = context.JK.ProfileUtils
@root = $(@getDOMNode())
@endOfList = @root.find('.end-of-payments-list')
@contentBodyScroller = @root
- @root = $(@getDOMNode())
@iCheckify()
componentDidUpdate: (prevProps, prevState) ->
diff --git a/web/app/assets/javascripts/react-components/RateUserDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/RateUserDialog.js.jsx.coffee
index 889210ed4..79a3f895a 100644
--- a/web/app/assets/javascripts/react-components/RateUserDialog.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/RateUserDialog.js.jsx.coffee
@@ -2,10 +2,19 @@ context = window
@RateUserDialog = React.createClass({
- mixins: [Reflux.listenTo(@AppStore, "onAppInit")]
+ mixins: [ICheckMixin,
+ Reflux.listenTo(@AppStore, "onAppInit")]
teacher: false
- parseId:(id) ->
+ getInitialState: () ->
+ {
+ id: null,
+ type: null,
+ student: null,
+ teacher: null,
+ rating: null,
+ }
+ parseId: (id) ->
if !id?
{id: null, type: null}
else
@@ -17,17 +26,25 @@ context = window
beforeShow: (args) ->
logger.debug("RateUserDialog.beforeShow", args.d1)
- @firstName = ''
- @lastName = ''
- @email = ''
+ parsed = @parseId(args.d1)
- @setState({target: null})
+ @setState({student: null, teacher: null, type: parsed.type, id: parsed.id, rating: null})
+
+ rest.getUserDetail({id: parsed.id}).done((response) => @userLookupDone(response)).fail((jqXHR) => @userLookupFail(jqXHR))
- rest.getUserDetail({id: args.d1}).done((response) => @userLookupDone(response)).fail((jqXHR) => @userLookupFail(jqXHR))
afterHide: () ->
+ isRatingTeacher: () ->
+ !@isRatingStudent()
+
+ isRatingStudent: () ->
+ @state.type == 'student'
+
userLookupDone: (response) ->
- @setState({target: response})
+ if @isRatingTeacher()
+ @setState({teacher: response})
+ else
+ @setState({student: response})
userLookupFail: (jqXHR) ->
@app.ajaxError(jqXHR, null, null)
@@ -38,50 +55,121 @@ context = window
'afterHide': @afterHide
};
- @app.bindDialog('rate-user', dialogBindings);
+ @app.bindDialog('rate-user-dialog', dialogBindings);
+ checkboxChanged: (e) ->
+ $target = $(e.target)
+ @setState({rating: $target.val()})
componentDidMount: () ->
+ @checkboxes = [{selector: 'input[name="rating"]', stateKey: 'rating'}]
+
@root = $(@getDOMNode())
- getInitialState: () ->
- {inviteErrors: null}
+ @iCheckify()
+
+ componentDidUpdate: () ->
+ @iCheckify()
+
+ descriptionChanged: (e) ->
+ @setState({description: $(e.target).val()})
doCancel: (e) ->
e.preventDefault()
- @app.layout.closeDialog('rate-user', true);
+ @app.layout.cancelDialog('rate-user-dialog');
doRating: (e) ->
e.preventDefault()
- rest.createReview({id: target})
+ if @disabled()
+ return
- createDone:(response) ->
- context.SchoolActions.addInvitation(@state.teacher, response)
- context.JK.Banner.showNotice("invitation sent", "Your invitation has been sent!")
- @app.layout.closeDialog('invite-school-user')
+ if @isRatingTeacher()
+ data =
+ {
+ target_id: @state.id
+ target_type: 'JamRuby::Teacher'
+ }
+ else
+ data =
+ {
+ target_id: @state.id,
+ target_type: 'JamRuby::User',
+ }
- createFail: (jqXHR) ->
+ data.rating = @state.rating
+ data.description = @state.description
+ rest.createReview(data).done((response) => @createReviewDone(response)).fail((jqXHR) => @createReviewFail(jqXHR))
+ createReviewDone: (response) ->
+ if @isRatingTeacher()
+ context.JK.Banner.showNotice("teacher rated", "Thank you for taking the time to provide your feedback.")
+ else
+ context.JK.Banner.showNotice("student rated", "Thank you for taking the time to provide your feedback.")
+
+ @app.layout.closeDialog('rate-user-dialog')
+
+ createReviewFail: (jqXHR) ->
handled = false
if jqXHR.status == 422
- errors = JSON.parse(jqXHR.responseText)
- @setState({inviteErrors: errors})
- handled = true
+ response = JSON.parse(jqXHR.responseText)
+ if response.errors.target?
+ @app.layout.notify({title: "not allowed", text: "you can not rate someone until you have had a lesson with them"})
+ handled = true
if !handled
@app.ajaxError(jqXHR, null, null)
- render: () ->
+ disabled: () ->
+ !@state.rating? || (!@state.teacher? && !@state.student?)
- if @state.user?.teacher?
+ render: () ->
+ submitClasses = classNames({'button-orange': true, disabled: @disabled()})
+ if @isRatingTeacher()
title = 'Rate Teacher'
- help = `Please rate this teacher based on your experience with them.
`
+ help = `Please rate this teacher based on your experience with them:
`
+ descriptionPrompt = `Please help other students by explaining what you like or don’t like about this teacher:
`
+ choices =
+ ``
else
title = 'Rate Student'
- help = `Please rate this student based on your experience with them.
`
-
+ help = `Please rate this student based on your experience with them:
`
+ descriptionPrompt = `Please help other teachers by explaining what you like or don’t like about this student:
`
+ choices =
+ ``
`
@@ -93,9 +181,17 @@ context = window
{help}
+ {choices}
+
+
+ {descriptionPrompt}
+
+
+
`
diff --git a/web/app/assets/javascripts/react-components/SessionLeaveBtn.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionLeaveBtn.js.jsx.coffee
index a11467e65..6286a0bbf 100644
--- a/web/app/assets/javascripts/react-components/SessionLeaveBtn.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/SessionLeaveBtn.js.jsx.coffee
@@ -4,16 +4,9 @@ context = window
onLeave: (e) ->
e.preventDefault()
- @rateSession()
SessionActions.leaveSession.trigger({location: '/client#/home'})
- rateSession: () ->
- unless @rateSessionDialog?
- @rateSessionDialog = new context.JK.RateSessionDialog(context.JK.app);
- @rateSessionDialog.initialize();
-
- @rateSessionDialog.showDialog();
render: () ->
`
diff --git a/web/app/assets/javascripts/react-components/TeacherProfile.js.jsx.coffee b/web/app/assets/javascripts/react-components/TeacherProfile.js.jsx.coffee
index bed688d7b..25ac26c0d 100644
--- a/web/app/assets/javascripts/react-components/TeacherProfile.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/TeacherProfile.js.jsx.coffee
@@ -1,6 +1,7 @@
context = window
rest = context.JK.Rest()
logger = context.JK.logger
+EVENTS = context.JK.EVENTS;
SubjectStore = context.SubjectStore
InstrumentStore = context.InstrumentStore
@@ -117,8 +118,20 @@ proficiencyDescriptionMap = {
@visible = true
logger.debug("TeacherProfile: afterShow")
@setState({userId: e.id, user: null})
+ @updateProfileInfo(e.id)
+
+ if $.QueryString['tile']?
+ rewrite = true
+ @setState({selected: $.QueryString['tile']})
+
+ if rewrite
+ if window.history.replaceState #ie9 proofing
+ window.history.replaceState({}, "", "/client#/profile/teacher/#{e.id}")
+
+
+ updateProfileInfo: (id) ->
rest.getUserDetail({
- id: e.id,
+ id: id,
show_teacher: true,
show_profile: true
}).done((response) => @userDetailDone(response)).fail(@app.ajaxError)
@@ -549,6 +562,12 @@ proficiencyDescriptionMap = {
{this.musicSamples(user, teacher)}
`
+ rateTeacher: (e) ->
+ @app.layout.showDialog('rate-user-dialog', {d1: "teacher_#{@state.user.id}"}).one(EVENTS.DIALOG_CLOSED, (e, data) =>
+ if !data.canceled
+ @updateProfileInfo(@state.userId)
+ )
+
ratings: () ->
user = @state.user
teacher = user.teacher
@@ -581,7 +600,8 @@ proficiencyDescriptionMap = {
`
Ratings & Reviews
-
{user.first_name} Summary Rating:
({reviewCount})
+
{user.first_name} Summary Rating:
({reviewCount})
RATE TEACHER
+
{reviews}
`
diff --git a/web/app/assets/javascripts/react-components/mixins/ICheckMixin.js.coffee b/web/app/assets/javascripts/react-components/mixins/ICheckMixin.js.coffee
index 2964025de..0bf3cda13 100644
--- a/web/app/assets/javascripts/react-components/mixins/ICheckMixin.js.coffee
+++ b/web/app/assets/javascripts/react-components/mixins/ICheckMixin.js.coffee
@@ -21,11 +21,15 @@ teacherActions = window.JK.Actions.Teacher
$candidate = @root.find(selector)
+
@iCheckIgnore = true
if $candidate.attr('type') == 'radio'
- $found = @root.find(selector + '[value="' + choice + '"]')
- $found.iCheck('check').attr('checked', true)
+ if choice?
+ $found = @root.find(selector + '[value="' + choice + '"]')
+ $found.iCheck('check').attr('checked', true)
+ else
+ $candidate.iCheck('uncheck').attr('checked', false)
else
if choice
$candidate.iCheck('check').attr('checked', true);
@@ -54,5 +58,5 @@ teacherActions = window.JK.Actions.Teacher
if @checkboxChanged?
@checkboxChanged(e)
else
- logger.warn("no checkbox changed implemented")
+ logger.error("no checkbox changed defined")
}
\ No newline at end of file
diff --git a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
index def7bfe56..0d00065b1 100644
--- a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
+++ b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
@@ -1072,6 +1072,19 @@ ConfigureTracksActions = @ConfigureTracksActions
@sessionUtils.SessionPageLeave()
+ if @currentSession?.lesson_session?
+ if context.JK.currentUserId == @currentSession.lesson_session.teacher_id
+ @app.layout.showDialog('rate-user-dialog', {d1: 'student_' + @currentSession.lesson_session.student_id})
+ else
+ @app.layout.showDialog('rate-user-dialog', {d1: 'teacher_' + @currentSession.lesson_session.student_id})
+
+ else
+ unless @rateSessionDialog?
+ @rateSessionDialog = new context.JK.RateSessionDialog(context.JK.app);
+ @rateSessionDialog.initialize();
+
+ @rateSessionDialog.showDialog();
+
leaveSession: () ->
if !@joinDeferred? || @joinDeferred?.state() == 'resolved'
diff --git a/web/app/assets/stylesheets/client/react-components/TeacherProfile.css.scss b/web/app/assets/stylesheets/client/react-components/TeacherProfile.css.scss
index 66c256f58..2f0412533 100644
--- a/web/app/assets/stylesheets/client/react-components/TeacherProfile.css.scss
+++ b/web/app/assets/stylesheets/client/react-components/TeacherProfile.css.scss
@@ -225,6 +225,12 @@
color:$ColorTextTypical;
}
+ .rate-teacher-btn {
+ margin-left: 36px;
+ top: -2px;
+ position: relative;
+ }
+
.review {
border-width:1px 0 0 0;
border-color:$ColorTextTypical;
diff --git a/web/app/assets/stylesheets/dialogs/rateUserDialog.css.scss b/web/app/assets/stylesheets/dialogs/rateUserDialog.css.scss
new file mode 100644
index 000000000..2d3a6606c
--- /dev/null
+++ b/web/app/assets/stylesheets/dialogs/rateUserDialog.css.scss
@@ -0,0 +1,52 @@
+@import "client/common";
+
+#rate-user-dialog {
+ width: 600px;
+ max-height:600px;
+
+ h2 {
+ color:white;
+ margin-bottom:10px;
+ font-size:16px;
+ }
+ .dialog-inner {
+ width: auto;
+ height:calc(100% - 29px)
+ }
+
+ .field {
+ margin-bottom:10px;
+ }
+
+ input {
+ display:inline-block;
+ }
+ label {
+ display:inline-block;
+ }
+ .iradio_minimal {
+ display:inline-block;
+ margin-right: 5px;
+ top: 4px;
+ }
+
+ textarea {
+ width:100%;
+ height:80px;
+ margin:0;
+ }
+
+ div[data-react-class="RateUserDialog"] {
+
+ }
+ .field.description {
+ margin-bottom:20px;
+ h2 {
+ margin-top: 20px;
+ }
+ }
+ .actions {
+ float:right;
+ margin:0 -13px 30px 0;
+ }
+}
\ No newline at end of file
diff --git a/web/app/controllers/api_reviews_controller.rb b/web/app/controllers/api_reviews_controller.rb
index dcdd8d3b0..99480b9c0 100644
--- a/web/app/controllers/api_reviews_controller.rb
+++ b/web/app/controllers/api_reviews_controller.rb
@@ -15,7 +15,21 @@ class ApiReviewsController < ApiController
# Create a review:
def create
- @review = Review.create(params)
+ target = User.find(params['target_id'])
+ if params[:target_type] == 'JamRuby::Teacher'
+ target = target.teacher
+ end
+
+ params[:target] = target
+ params[:user] = current_user
+
+ @review = Review.create_or_update(params)
+
+ puts "@review.errors #{@review.errors.inspect}"
+ if @review.errors.any?
+ respond_with_model(@review)
+ return
+ end
end
# List reviews matching targets for given review summary:
diff --git a/web/app/views/dialogs/_dialogs.html.haml b/web/app/views/dialogs/_dialogs.html.haml
index ae4d9e5fb..4c0ed3f1d 100644
--- a/web/app/views/dialogs/_dialogs.html.haml
+++ b/web/app/views/dialogs/_dialogs.html.haml
@@ -53,3 +53,4 @@
= render 'dialogs/chatDialog'
= render 'dialogs/cancelLessonDialog'
= render 'dialogs/rescheduleLessonDialog'
+= render 'dialogs/rateUserDialog'
diff --git a/web/app/views/dialogs/_rateUserDialog.html.slim b/web/app/views/dialogs/_rateUserDialog.html.slim
new file mode 100644
index 000000000..111c3916d
--- /dev/null
+++ b/web/app/views/dialogs/_rateUserDialog.html.slim
@@ -0,0 +1,2 @@
+.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='rate-user-dialog' id='rate-user-dialog'
+ = react_component 'RateUserDialog', {}
diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb
index f8042d0ce..0113ea09a 100644
--- a/web/config/environments/development.rb
+++ b/web/config/environments/development.rb
@@ -107,4 +107,5 @@ SampleApp::Application.configure do
config.vst_enabled = true
config.verify_email_enabled = true
+ config.jamclass_enabled = true
end
diff --git a/web/config/environments/test.rb b/web/config/environments/test.rb
index e0ad3315c..00e39413b 100644
--- a/web/config/environments/test.rb
+++ b/web/config/environments/test.rb
@@ -115,5 +115,6 @@ SampleApp::Application.configure do
:secret_key => 'sk_test_OkjoIF7FmdjunyNsdVqJD02D',
:source_customer => 'cus_88Vp44SLnBWMXq'
}
+ config.jamclass_enabled = true
end