* VRFS-2456 - add listen function to find session page, and update of join/rsvp icons
This commit is contained in:
parent
3bac8252e9
commit
9876c00a7a
|
|
@ -14,11 +14,11 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.mount_source_up_requested(mount)
|
||||
Notification.send_subscription_message('mount', mount.id, {type: 'source_up_requested'}.to_json )
|
||||
Notification.send_subscription_message('mount', mount.id, {change_type: IcecastSourceChange::CHANGE_TYPE_MOUNT_UP_REQUEST}.to_json )
|
||||
end
|
||||
|
||||
def self.mount_source_down_requested(mount)
|
||||
Notification.send_subscription_message('mount', mount.id, {type: 'source_down_requested'}.to_json )
|
||||
Notification.send_subscription_message('mount', mount.id, {change_type: IcecastSourceChange::CHANGE_TYPE_MOUNT_DOWN_REQUEST}.to_json )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ module JamRuby
|
|||
#IcecastSourceChange.delete_all(["icecast_mount_id = ?", self.id]) if source_direction
|
||||
|
||||
# and tell anyone listening that the direction has changed
|
||||
SubscriptionMessage.mount_source_direction(self)
|
||||
# SubscriptionMessage.mount_source_direction(self)
|
||||
end
|
||||
|
||||
# Note:
|
||||
|
|
@ -139,7 +139,7 @@ module JamRuby
|
|||
first = source_changes.first
|
||||
|
||||
# don't check source_changes if actual source state mirrors desired source state... just say we are good, and pass down relevant sourcing user ID if present
|
||||
result = success_state('source_' + (source_direction ? 'up' : 'down'), first.nil? ? nil : first.user_id)
|
||||
result = success_state('source_' + (sourced ? 'up' : 'down'), first.nil? ? nil : first.user_id)
|
||||
|
||||
elsif source_changes.count > 0
|
||||
# if the desired source direction is up, but we haven't sourced yet... let's try and find out why
|
||||
|
|
@ -200,7 +200,7 @@ module JamRuby
|
|||
def source_up
|
||||
with_lock do
|
||||
self.sourced = true
|
||||
self.sourced_needs_changing_at = nil
|
||||
self.sourced_needs_changing_at = Time.now
|
||||
self.no_config_changed = true
|
||||
save(validate: false)
|
||||
end
|
||||
|
|
@ -209,7 +209,7 @@ module JamRuby
|
|||
def source_down
|
||||
with_lock do
|
||||
self.sourced = false
|
||||
self.sourced_needs_changing_at = nil
|
||||
self.sourced_needs_changing_at = Time.now
|
||||
self.no_config_changed = true
|
||||
save(validate: false)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ describe IcecastMount do
|
|||
let(:mount_needing_source) {FactoryGirl.create(:iceast_mount_with_music_session, sourced: false, sourced_needs_changing_at: Time.now, listeners: 1)}
|
||||
|
||||
it "happy sourced mount" do
|
||||
sourced_mount.state.should == success_state('source_down')
|
||||
sourced_mount.state.should == success_state('source_up')
|
||||
end
|
||||
|
||||
it "just transitioned" do
|
||||
|
|
@ -317,7 +317,7 @@ describe IcecastMount do
|
|||
it "happy sourced mount" do
|
||||
mount_needing_source.sourced = true
|
||||
mount_needing_source.save!
|
||||
mount_needing_source.state.should == success_state('source_down', change1.user.id)
|
||||
mount_needing_source.state.should == success_state('source_up', change1.user.id)
|
||||
end
|
||||
|
||||
it "succeeded recently in correct transition" do
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
|
|
@ -44,7 +44,8 @@
|
|||
MUTE_SELECTED: 'mute_selected',
|
||||
SUBSCRIBE_NOTIFICATION: 'subscribe_notification',
|
||||
CONNECTION_UP: 'connection_up',
|
||||
CONNECTION_DOWN: 'connection_down'
|
||||
CONNECTION_DOWN: 'connection_down',
|
||||
SCREEN_CHANGED: 'screen_changed'
|
||||
};
|
||||
|
||||
context.JK.ALERT_NAMES = {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
var WAIT_FOR_BUFFER_TIMEOUT = 5000;
|
||||
var RETRY_ATTEMPTS = 5; // we try 4 times, so the user will wait up until RETRY_ATTEMPTS * WAIT_FOR_BUFFER_TIMEOUTS
|
||||
|
||||
|
||||
var logger = context.JK.logger;
|
||||
var rest = context.JK.Rest();
|
||||
var $parent = $parentElement;
|
||||
|
|
@ -44,10 +43,15 @@
|
|||
var musicSessionId = null;
|
||||
var waitForBufferingTimeout = null;
|
||||
var fanAccess = null;
|
||||
var audioSrc = null;
|
||||
var audioType = null;
|
||||
var retryAttempts = 0;
|
||||
var self = this;
|
||||
var mountInfo = null;
|
||||
var $mountState = null;
|
||||
var lazyAudioInit = options && options.lazyAudioInit;
|
||||
var hoverOptions = (options && options.hoverOptions) ? options.hoverOptions : {}
|
||||
var $detailHelper = options && options.detailHelper;
|
||||
|
||||
var destroyed = false;
|
||||
|
||||
|
|
@ -73,6 +77,18 @@
|
|||
e.stopPropagation();
|
||||
}
|
||||
|
||||
if(lazyAudioInit) {
|
||||
if($audio.length == 0) {
|
||||
$audio =
|
||||
$('<audio preload="none">' +
|
||||
'<source src="' + audioSrc + '" type="' + audioType + '" />' +
|
||||
'</audio>')
|
||||
$parent.append($audio)
|
||||
audioDomElement = $audio.get(0);
|
||||
audioBind();
|
||||
}
|
||||
}
|
||||
|
||||
if(destroyed) return;
|
||||
|
||||
if(!audioDomElement) throw "no audio element supplied; the user should not be able to attempt a play"
|
||||
|
|
@ -117,7 +133,7 @@
|
|||
|
||||
if(destroyed) return;
|
||||
|
||||
if(!audioDomElement) throw "no audio element supplied; the user should not be able to attempt a pause"
|
||||
if(!lazyAudioInit && !audioDomElement) throw "no audio element supplied; the user should not be able to attempt a pause"
|
||||
|
||||
transition(PlayStateNone);
|
||||
|
||||
|
|
@ -133,6 +149,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
function onScreenChanged(e, data) {
|
||||
if(context.JK.ListenBroadcastCurrentlyPlaying) {
|
||||
context.JK.ListenBroadcastCurrentlyPlaying.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// this is the only way to make audio stop buffering after the user hits pause
|
||||
function recreateAudioElement() {
|
||||
// jeez: http://stackoverflow.com/questions/4071872/html5-video-force-abort-of-buffering/13302599#13302599
|
||||
|
|
@ -408,6 +430,8 @@
|
|||
logger.error("unknown state: " + playState)
|
||||
}
|
||||
|
||||
$parent.data('listenbroadcast-playstate', playState);
|
||||
|
||||
$parent.triggerHandler('statechange.listenBroadcast',
|
||||
{
|
||||
element: $parent,
|
||||
|
|
@ -509,7 +533,9 @@
|
|||
|
||||
logger.debug("subscription notification received: type:" + data.type)
|
||||
|
||||
updateMountInfo(data.body.mount);
|
||||
if(data.body.mount) {
|
||||
updateMountInfo(data.body.mount);
|
||||
}
|
||||
|
||||
var id = data.id
|
||||
var type = data.type
|
||||
|
|
@ -519,7 +545,7 @@
|
|||
var $detailHolder = $mountState.find('.detail-items')
|
||||
var msgType = data.body.type;
|
||||
|
||||
var sourceChange = data.body.source_change;
|
||||
var sourceChange = data.body;
|
||||
if(sourceChange) {
|
||||
var $detail = addSourceChange($detailHolder, sourceChange)
|
||||
if ($detail) {
|
||||
|
|
@ -549,8 +575,8 @@
|
|||
$detailText.text('Start Broadcast Requested')
|
||||
}
|
||||
else if(sourceChange.change_type == 'source_down_request') {
|
||||
$who.text('<span>Server</span>')
|
||||
$detailText.text('Start Broadcast Requested')
|
||||
$who.html('<span>Server</span>')
|
||||
$detailText.text('Stop Broadcast Requested')
|
||||
}
|
||||
else {
|
||||
|
||||
|
|
@ -597,43 +623,61 @@
|
|||
return $detail;
|
||||
}
|
||||
|
||||
function cleanupDetails() {
|
||||
var mountId = $parent.data('mount-id')
|
||||
if(mountId) {
|
||||
context.JK.SubscriptionUtils.unsubscribe('mount', mountId)
|
||||
}
|
||||
$mountState = null;
|
||||
mountInfo = null;
|
||||
}
|
||||
|
||||
function openBubble() {
|
||||
checkServer().done(function(response) {
|
||||
var mountId = response.mount ? response.mount.id : null
|
||||
|
||||
if(mountId) {
|
||||
rest.getMount({id: mountId})
|
||||
.done(function (mount) {
|
||||
mountInfo = mount
|
||||
$parent.data('mount-id', mountId)
|
||||
context.JK.SubscriptionUtils.subscribe('mount', mountId).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, onDetailEvent)
|
||||
$parent.btOn()
|
||||
})
|
||||
.fail(context.JK.app.ajaxError)
|
||||
}
|
||||
else {
|
||||
mountInfo = null;
|
||||
context.JK.app.layout.notify('This session can not currently broadcast')
|
||||
}
|
||||
})
|
||||
.fail(function() {
|
||||
logger.debug("session is over")
|
||||
})
|
||||
}
|
||||
|
||||
function bindHoverDetail() {
|
||||
|
||||
var stateHolderHtml = context._.template($('#template-listen-broadcast-state').html(), {}, {variable: 'data'});
|
||||
context.JK.hoverBubble($parent, stateHolderHtml, {trigger: 'none', preShow: broadcastDetailPreShow, positions:['bottom'], width:'300px', height:'250px'})
|
||||
var btOptions = $.extend({}, {trigger: 'none', preShow: broadcastDetailPreShow, postHide: cleanupDetails, closeWhenOthersOpen: true, positions:['bottom', 'right', 'top', 'left'], width:'300px', height:'250px'}, hoverOptions)
|
||||
context.JK.hoverBubble($parent, stateHolderHtml, btOptions)
|
||||
|
||||
$parent.hoverIntent({
|
||||
over: function() {
|
||||
checkServer().done(function(response) {
|
||||
var mountId = response.mount ? response.mount.id : null
|
||||
// in case the bt is destroyed
|
||||
$parent.on('remove', cleanupDetails);
|
||||
|
||||
if(mountId) {
|
||||
rest.getMount({id: mountId})
|
||||
.done(function (mount) {
|
||||
mountInfo = mount
|
||||
$parent.data('mount-id', mountId)
|
||||
context.JK.SubscriptionUtils.subscribe('mount', mountId).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, onDetailEvent)
|
||||
$parent.btOn()
|
||||
})
|
||||
.fail(context.JK.app.ajaxError)
|
||||
}
|
||||
else {
|
||||
mountInfo = null;
|
||||
context.JK.app.layout.notify('This session can not currently broadcast')
|
||||
}
|
||||
})
|
||||
.fail(function() {
|
||||
logger.debug("session is over")
|
||||
})
|
||||
},
|
||||
out: function() {
|
||||
var mountId = $parent.data('mount-id')
|
||||
context.JK.SubscriptionUtils.unsubscribe('mount', mountId)
|
||||
$parent.btOff();
|
||||
$mountState = null;
|
||||
mountInfo = null;
|
||||
}
|
||||
})
|
||||
if($detailHelper) {
|
||||
$detailHelper.click(function() { openBubble(); return false; })
|
||||
}
|
||||
else {
|
||||
$parent.hoverIntent({
|
||||
over: function() {
|
||||
openBubble();
|
||||
},
|
||||
out: function() {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
function initialize() {
|
||||
|
||||
|
|
@ -645,23 +689,35 @@
|
|||
if(fanAccess === null) throw 'fan-access must be specified in $parentElement';
|
||||
fanAccess = $parent.attr('fan-access') === 'true' // coerce to boolean
|
||||
|
||||
if(lazyAudioInit) {
|
||||
audioSrc = $parent.attr('data-audio-src');
|
||||
if(audioSrc === null) throw 'data-audio-src must be specified in $parentElement';
|
||||
audioType = $parent.attr('data-audio-type');
|
||||
if(audioType === null) throw 'data-audio-type must be specified in $parentElement';
|
||||
}
|
||||
|
||||
bindHoverDetail();
|
||||
|
||||
$audio = $('audio', $parent);
|
||||
|
||||
if($audio.length == 0) {
|
||||
if($audio.length == 0 && !lazyAudioInit) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($audio.length > 1) {
|
||||
throw "more than one <audio> element found";
|
||||
}
|
||||
|
||||
audioDomElement = $audio.get(0);
|
||||
audioBind();
|
||||
if(!lazyAudioInit) {
|
||||
audioDomElement = $audio.get(0);
|
||||
audioBind();
|
||||
}
|
||||
|
||||
$parent.bind('play.listenBroadcast', play);
|
||||
$parent.bind('pause.listenBroadcast', pause);
|
||||
$parent.bind('destroy.listenBroadcast', destroy);
|
||||
|
||||
$(document).on(context.JK.EVENTS.SCREEN_CHANGED, onScreenChanged);
|
||||
}
|
||||
|
||||
initialize();
|
||||
|
|
|
|||
|
|
@ -542,6 +542,8 @@
|
|||
|
||||
logger.debug("Changing screen to " + currentScreen);
|
||||
|
||||
$(document).triggerHandler(EVENTS.SCREEN_CHANGED, {previousScreen: previousScreen, newScreen: currentScreen})
|
||||
|
||||
screenEvent(currentScreen, 'beforeShow', data);
|
||||
|
||||
// For now -- it seems we want it open always.
|
||||
|
|
|
|||
|
|
@ -18,11 +18,63 @@
|
|||
var $latencyTemplate = $('#template-latency');
|
||||
var $musicianTemplate = $('#template-musician-info');
|
||||
var showJoinLink = true;
|
||||
var showListenLink = true;
|
||||
var showRsvpLink = true;
|
||||
|
||||
function renderActiveSession(session, tbGroup, myAudioLatency) {
|
||||
// related to listen
|
||||
function stateChange(e, data) {
|
||||
var $listenLink = e.element;
|
||||
var $listenText = $('.listen-link-text', $listenLink);
|
||||
var $listenDetails = $('.listen-link-details', $listenLink);
|
||||
|
||||
$('#actionHeader', tbGroup).html('JOIN');
|
||||
if(data.displayText)
|
||||
{
|
||||
if(data.state == 'playing') {
|
||||
$listenText.text('Stop Listening')
|
||||
}
|
||||
else {
|
||||
$listenText.text(context.JK.toTitleCase(data.displayText))
|
||||
$listenDetails.addClass('statusing')
|
||||
}
|
||||
}
|
||||
|
||||
if(data.isEnd) {
|
||||
$listenText.text('Listen').removeClass('statusing')
|
||||
stopPlay();
|
||||
}
|
||||
|
||||
if(data.isSessionOver) {
|
||||
$listenLink.removeClass('inprogress').addClass('ended')
|
||||
}
|
||||
}
|
||||
|
||||
function startPlay($listenLink) {
|
||||
$listenLink.find('img').attr('src', '/assets/content/pause-icon.jpg');
|
||||
$listenLink.trigger('play.listenBroadcast');
|
||||
}
|
||||
|
||||
function stopPlay($listenLink) {
|
||||
$listenLink.find('img').attr('src', '/assets/content/listen-icon.jpg');
|
||||
$listenLink.trigger('pause.listenBroadcast');
|
||||
}
|
||||
|
||||
function togglePlay() {
|
||||
var $listenLink = $(this)
|
||||
var $listenText = $('.listen-link-text', $listenLink);
|
||||
var $listenDetails = $('.listen-link-details', $listenLink);
|
||||
if($listenLink.data('listenbroadcast-playstate') == 'playing') {
|
||||
$listenText.text('Listen')
|
||||
$listenDetails.removeClass('statusing')
|
||||
stopPlay($listenLink);
|
||||
}
|
||||
else {
|
||||
startPlay($listenLink);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function renderActiveSession(session, tbGroup, myAudioLatency) {
|
||||
|
||||
var i = 0;
|
||||
var inSessionUsersHtml = '', rsvpFirst3UsersHtml = '', rsvpRemainingUsersHtml = '', openSlotsFirst3Html = '', openSlotsRemainingHtml = '', latencyInSessionHtml = '', latencyFirst3Html = '', latencyRemainingHtml = '', notationFileHtml = '';
|
||||
|
|
@ -32,6 +84,8 @@
|
|||
var inSessionUsers = [];
|
||||
|
||||
showJoinLink = session.musician_access;
|
||||
console.log('session', session)
|
||||
showListenLink = session.fan_access && session.active_music_session && session.active_music_session.mount;
|
||||
|
||||
// render musicians who are already in the session
|
||||
if (session.active_music_session && "participants" in session.active_music_session && session.active_music_session.participants.length > 0) {
|
||||
|
|
@ -100,6 +154,7 @@
|
|||
var sessionVals = buildSessionObject(session, notationFileHtml, rsvpFirst3UsersHtml, rsvpRemainingUsersHtml, openSlotsFirst3Html, openSlotsRemainingHtml, latencyFirst3Html, latencyRemainingHtml, latencyInSessionHtml);
|
||||
sessionVals.in_session_musicians = inSessionUsersHtml.length > 0 ? inSessionUsersHtml : 'N/A';
|
||||
sessionVals.join_link_display_style = showJoinLink ? "block" : "none";
|
||||
sessionVals.listen_link_display_style = showListenLink ? "inline-block" : "none";
|
||||
|
||||
var $row = $(context.JK.fillTemplate($activeSessionTemplate.html(), sessionVals));
|
||||
var $offsetParent = $(tbGroup).closest('.content');
|
||||
|
|
@ -134,6 +189,26 @@
|
|||
});
|
||||
});
|
||||
|
||||
// enable listen button
|
||||
|
||||
if(showListenLink) {
|
||||
var $listenLink = $('.listen-link', $parentRow)
|
||||
var $listenText = $('.listen-link-text', $parentRow)
|
||||
var $listenDetailHover = $('.listen-detail-hover', $parentRow)
|
||||
$listenLink.parent().hoverIntent({
|
||||
over: function() {
|
||||
$listenDetailHover.show();
|
||||
},
|
||||
out: function() {
|
||||
$listenDetailHover.hide();
|
||||
}
|
||||
})
|
||||
$listenLink.attr('data-music-session', session.id).attr('fan-access', session.fan_access).attr('data-audio-src', session.active_music_session.mount.url).attr('data-audio-type', session.active_music_session.mount.mime_type)
|
||||
$listenLink.listenBroadcast({lazyAudioInit:true, hoverOptions: {offsetParent: $offsetParent}, detailHelper: $listenDetailHover});
|
||||
$listenLink.bind('statechange.listenBroadcast', stateChange);
|
||||
$listenLink.click(togglePlay);
|
||||
}
|
||||
|
||||
if (showJoinLink) {
|
||||
// wire up the Join Link to the T&Cs dialog
|
||||
$('.join-link', $parentRow).click(function(evt) {
|
||||
|
|
@ -171,8 +246,6 @@
|
|||
var hasPendingOrDeclinedRsvp = false;
|
||||
var openRsvps = session.open_rsvps;
|
||||
|
||||
$('#actionHeader', tbGroup).html('RSVP');
|
||||
|
||||
var i = 0;
|
||||
var rsvpFirst3UsersHtml = '', rsvpRemainingUsersHtml = '', openSlotsFirst3Html = '', openSlotsRemainingHtml = '', latencyFirst3Html = '', latencyRemainingHtml = '', notationFileHtml = '';
|
||||
|
||||
|
|
@ -285,7 +358,7 @@
|
|||
|
||||
if (approvedRsvpId) {
|
||||
showRsvpLink = false;
|
||||
noLinkText = $('<span class="text">You have been confirmed for this session. <a href="#">Cancel</a></span>');
|
||||
noLinkText = $('<span class="text">You have been confirmed for this session. <a href="#" style="color: #fc0">Cancel</a></span>');
|
||||
noLinkText.find('a').click(function() {
|
||||
ui.launchRsvpCancelDialog(session.id, approvedRsvpId)
|
||||
.one(EVENTS.RSVP_CANCELED, function() {
|
||||
|
|
@ -302,7 +375,7 @@
|
|||
}
|
||||
else if (pendingRsvpId) {
|
||||
showRsvpLink = false;
|
||||
noLinkText = $('<span class="text">You have RSVP\'ed to this session. <a href="#">Cancel</a></span>');
|
||||
noLinkText = $('<span class="text">You have RSVP\'ed to this session. <a href="#" style="color: #fc0">Cancel</a></span>');
|
||||
noLinkText.find('a').click(function() {
|
||||
ui.launchRsvpCancelDialog(session.id, pendingRsvpId)
|
||||
.one(EVENTS.RSVP_CANCELED, function() {
|
||||
|
|
|
|||
|
|
@ -213,6 +213,10 @@
|
|||
return;
|
||||
}
|
||||
|
||||
$element.on('remove', function() {
|
||||
$element.btOff();
|
||||
})
|
||||
|
||||
if ($element instanceof jQuery) {
|
||||
if ($element.length == 0) {
|
||||
logger.error("hoverBubble: no element specified with text %o", text);
|
||||
|
|
@ -449,6 +453,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/4878756/javascript-how-to-capitalize-first-letter-of-each-word-like-a-2-word-city
|
||||
context.JK.toTitleCase = function(str) {
|
||||
return str.replace(/\w\S*/g, function(txt){
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||
|
|
|
|||
|
|
@ -85,4 +85,42 @@
|
|||
.latency-value {
|
||||
@include border-radius(2px);
|
||||
}
|
||||
|
||||
.action-links {
|
||||
a { margin-top:10px; }
|
||||
}
|
||||
|
||||
.listen-link-details {
|
||||
position:relative;
|
||||
left:6px;
|
||||
|
||||
&.statusing {
|
||||
left:0;
|
||||
}
|
||||
}
|
||||
|
||||
.listen-detail-hover {
|
||||
margin-left:5px;
|
||||
margin-top:0 !important;
|
||||
color: #fc0;
|
||||
display:none;
|
||||
}
|
||||
|
||||
.join-link {
|
||||
position:relative;
|
||||
left:-3px;
|
||||
}
|
||||
.join-link-text {
|
||||
position:relative;
|
||||
left:6px;
|
||||
}
|
||||
|
||||
.rsvp-link {
|
||||
position:relative;
|
||||
left:0px;
|
||||
}
|
||||
.rsvp-link-text {
|
||||
position:relative;
|
||||
left:6px;
|
||||
}
|
||||
}
|
||||
|
|
@ -43,12 +43,12 @@
|
|||
|
||||
&[data-status=source_up] {.source_up { display:inline-block; }}
|
||||
&[data-status=source_down] {.source_down { display:inline-block; }}
|
||||
&[data-status=source_wrong_up] {.source_up { display:inline-block; }}
|
||||
&[data-status=source_wrong_down] {.source_up { display:inline-block; }}
|
||||
&[data-status=transition_up] {.source_up { display:inline-block; }}
|
||||
&[data-status=transition_down] {.source_up { display:inline-block; }}
|
||||
&[data-status=transition_timeout_up] {.source_up { display:inline-block; }}
|
||||
&[data-status=transition_timeout_down] {.source_up { display:inline-block; }}
|
||||
&[data-status=source_wrong_up] {.source_wrong_up { display:inline-block; }}
|
||||
&[data-status=source_wrong_down] {.source_wrong_down { display:inline-block; }}
|
||||
&[data-status=transition_up] {.transition_up { display:inline-block; }}
|
||||
&[data-status=transition_down] {.transition_down { display:inline-block; }}
|
||||
&[data-status=transition_timeout_up] {.transition_timeout_up { display:inline-block; }}
|
||||
&[data-status=transition_timeout_down] {.transition_timeout_down { display:inline-block; }}
|
||||
&[data-status=unknown] {.unknown { display:inline-block; }}
|
||||
&[data-status=loading] {.loading { display:inline-block; }}
|
||||
&[data-status=db_error] {.db_error{ display:inline-block; }}
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
|
||||
.detail-items {
|
||||
|
||||
height:85px;
|
||||
height:80px;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -278,6 +278,12 @@
|
|||
|
||||
.link-contents {
|
||||
margin-bottom:20px;
|
||||
float:left;
|
||||
}
|
||||
|
||||
#btn-share-copy {
|
||||
top:-4px;
|
||||
position:relative;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ node do |source_change|
|
|||
partial("api_icecast/show_source_change", :object => source_change)
|
||||
end
|
||||
|
||||
child(:mount) { |mount|
|
||||
child(:mount => :mount) { |mount|
|
||||
attributes :id, :listeners, :source_direction, :sourced
|
||||
|
||||
node :state do |mount|
|
||||
|
|
|
|||
|
|
@ -91,6 +91,21 @@
|
|||
<td>Notation Files:</td>
|
||||
<td>{notation_files}</td>
|
||||
</tr>
|
||||
<tr class="action-links">
|
||||
<td>
|
||||
<a class="listen-link" style="display:{listen_link_display_style};">
|
||||
<%= image_tag "content/listen-icon.jpg", :size => "40x40" %>
|
||||
</a>
|
||||
<br/>
|
||||
<span class="listen-link-details"><span class="listen-link-text">Listen</span><a href="#" class="listen-detail-hover">?</a></span>
|
||||
</td>
|
||||
<td>
|
||||
<a class="join-link" style="display:{join_link_display_style};">
|
||||
<%= image_tag "content/join-icon.jpg", :size => "37x40" %>
|
||||
</a>
|
||||
<span class="join-link-text">Join</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td width="35%">
|
||||
|
|
@ -156,11 +171,6 @@
|
|||
<tr><td><span class="bold">Legal Policy:</span><br/>{legal_policy}</td></tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="noborder" style="text-align:center; vertical-align:middle;">
|
||||
<a class="join-link" style="display:{join_link_display_style};">
|
||||
<%= image_tag "content/icon_join.png", :size => "19x22" %>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
|
|
@ -183,6 +193,18 @@
|
|||
<tr>
|
||||
<td colspan="2">{scheduled_start}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<span class="rsvp-msg" style="display:none;">You cannot RSVP to this session.</span>
|
||||
<a class="rsvp-link">
|
||||
<%= image_tag "content/rsvp-icon.jpg", :size => "40x40" %>
|
||||
</a>
|
||||
<br/>
|
||||
<span class="rsvp-link-text">RSVP</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td width="35%">
|
||||
|
|
@ -235,12 +257,6 @@
|
|||
<tr><td><span class="bold">Legal Policy:</span><br/>{legal_policy}</td></tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="noborder rsvp-section">
|
||||
<span class="rsvp-msg" style="display:none;">You cannot RSVP to this session.</span>
|
||||
<a class="rsvp-link">
|
||||
<%= image_tag "content/icon_join.png", :size => "19x22" %>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@
|
|||
<th align="left" width="30%">SESSION</th>
|
||||
<th align="left" width="35%">MUSICIANS</th>
|
||||
<th width="10%" style="text-align:center">LATENCY</th>
|
||||
<th align="left" width="20%">POLICIES</th>
|
||||
<th id="actionHeader" class="noborder" width="30" style="text-align:center"></th>
|
||||
<th align="left" width="20%">POLICIES</th>
|
||||
</tr>
|
||||
<!-- session row goes here -->
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ UnusedMusicNotationCleaner:
|
|||
description: "Remove unused music notations"
|
||||
|
||||
UserProgressEmailer:
|
||||
cron: "30 21 * * *"
|
||||
# cron: "30 21 * * *"
|
||||
class: "JamRuby::UserProgressEmailer"
|
||||
description: "Sends periodic user progress emails"
|
||||
|
||||
DailySessionEmailer:
|
||||
cron: "0 6 * * *"
|
||||
# cron: "0 6 * * *"
|
||||
class: "JamRuby::DailySessionEmailer"
|
||||
description: "Sends daily scheduled session emails"
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ ScheduledMusicSessionCleaner:
|
|||
description: "Purges old, forgotten sessions that have not been started for >4 weeks"
|
||||
|
||||
NewMusicianEmailer:
|
||||
cron: "0 1 * * 1"
|
||||
# cron: "0 1 * * 1"
|
||||
class: "JamRuby::NewMusicianEmailer"
|
||||
description: "Sends weekly emails of new users with good latency"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue