Merge branch 'saas' into saas-embed-player

Conflicts:
	airtime_mvc/application/configs/ACL.php
This commit is contained in:
drigato 2015-03-31 17:44:14 -04:00
commit 220f21ab22
29 changed files with 422 additions and 149 deletions

View File

@ -24,12 +24,14 @@ require_once "FileIO.php";
require_once "OsPath.php";
require_once "Database.php";
require_once "ProvisioningHelper.php";
require_once "GoogleAnalytics.php";
require_once "Timezone.php";
require_once "Auth.php";
require_once __DIR__.'/forms/helpers/ValidationTypes.php';
require_once __DIR__.'/forms/helpers/CustomDecorators.php';
require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php';
require_once __DIR__.'/controllers/plugins/Maintenance.php';
require_once __DIR__.'/controllers/plugins/ConversionTracking.php';
require_once __DIR__.'/modules/rest/controllers/ShowImageController.php';
require_once __DIR__.'/modules/rest/controllers/MediaController.php';
@ -52,6 +54,7 @@ Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance());
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new RabbitMqPlugin());
$front->registerPlugin(new Zend_Controller_Plugin_ConversionTracking());
$front->throwExceptions(false);
//localization configuration

View File

@ -65,7 +65,9 @@ class Application_Common_FileIO
//We can have multiple levels of output buffering. Need to
//keep looping until all have been disabled!!!
//http://www.php.net/manual/en/function.ob-end-flush.php
while (@ob_end_flush());
while (ob_get_level() > 0) {
ob_end_flush();
}
// NOTE: We can't use fseek here because it does not work with streams
// (a.k.a. Files stored in the cloud)

View File

@ -0,0 +1,92 @@
<?php
class Application_Common_GoogleAnalytics
{
/** Returns a string containing the JavaScript code to pass some billing account info
* into Google Tag Manager / Google Analytics, so we can track things like the plan type.
*/
public static function generateGoogleTagManagerDataLayerJavaScript()
{
$code = "";
try {
$clientId = Application_Model_Preference::GetClientId();
$plan = Application_Model_Preference::GetPlanLevel();
$isTrial = ($plan == "trial");
//Figure out how long the customer has been around using a mega hack.
//(I'm avoiding another round trip to WHMCS for now...)
//We calculate it based on the trial end date...
$trialEndDateStr = Application_Model_Preference::GetTrialEndingDate();
if ($trialEndDateStr == '') {
$accountDuration = 0;
} else {
$today = new DateTime();
$trialEndDate = new DateTime($trialEndDateStr);
$trialDuration = new DateInterval("P30D"); //30 day trial duration
$accountCreationDate = $trialEndDate->sub($trialDuration);
$interval = $today->diff($accountCreationDate);
$accountDuration = $interval->days;
}
$code = "$( document ).ready(function() {
dataLayer.push({
'UserID': '" . $clientId . "',
'Customer': 'Customer',
'PlanType': '" . $plan . "',
'Trial': '" . $isTrial . "',
'AccountDuration': '" . strval($accountDuration) . "'
});
});";
//No longer sending these variables because we used to make a query to WHMCS
//to fetch them, which was slow.
// 'ZipCode': '" . $postcode . "',
// 'Country': '" . $country . "',
} catch (Exception $e) {
Logging::error($e);
return "";
}
return $code;
}
/** Generate the JavaScript snippet that logs a trial to paid conversion */
public static function generateConversionTrackingJavaScript()
{
$newPlan = Application_Model_Preference::GetPlanLevel();
$oldPlan = Application_Model_Preference::GetOldPlanLevel();
$code = "dataLayer.push({'event': 'Conversion',
'Conversion': 'Trial to Paid',
'Old Plan' : '$oldPlan',
'New Plan' : '$newPlan'});";
return $code;
}
/** Return true if the user used to be on a trial plan and was just converted to a paid plan. */
public static function didPaidConversionOccur($request)
{
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
if ($userInfo) {
$user = new Application_Model_User($userInfo->id);
} else {
return;
}
$oldPlan = Application_Model_Preference::GetOldPlanLevel();
if ($user->isSuperAdmin() &&
!$user->isSourcefabricAdmin() &&
$request->getControllerKey() !== "thank-you")
{
//Only tracking trial->paid conversions for now.
if ($oldPlan == "trial")
{
return true;
}
}
return false;
}
}

View File

@ -27,7 +27,7 @@ class Application_Common_HTTPHelper
if (empty($baseDir)) {
$baseDir = "/";
}
if ($baseDir[0] != "") {
if ($baseDir[0] != "/") {
$baseDir = "/" . $baseDir;
}

View File

@ -36,6 +36,7 @@ $ccAcl->add(new Zend_Acl_Resource('library'))
->add(new Zend_Acl_Resource('rest:media'))
->add(new Zend_Acl_Resource('rest:show-image'))
->add(new Zend_Acl_Resource('billing'))
->add(new Zend_Acl_Resource('thank-you'))
->add(new Zend_Acl_Resource('provisioning'))
->add(new Zend_Acl_Resource('embeddableplayer'));
@ -70,7 +71,11 @@ $ccAcl->allow('G', 'index')
->allow('A', 'user')
->allow('A', 'systemstatus')
->allow('A', 'preference')
<<<<<<< HEAD
->allow('A', 'embeddableplayer')
=======
->allow('S', 'thank-you')
>>>>>>> saas
->allow('S', 'billing');

View File

@ -44,6 +44,13 @@ class Config {
$CC_CONFIG['dev_env'] = 'production';
}
//Backported static_base_dir default value into saas for now.
if (array_key_exists('static_base_dir', $values['general'])) {
$CC_CONFIG['staticBaseDir'] = $values['general']['static_base_dir'];
} else {
$CC_CONFIG['staticBaseDir'] = '/';
}
// Parse separate conf file for cloud storage values
$cloudStorageConfig = "/etc/airtime-saas/".$CC_CONFIG['dev_env']."/cloud_storage.conf";
if (!file_exists($cloudStorageConfig)) {

View File

@ -35,7 +35,7 @@ class ShowbuilderController extends Zend_Controller_Action
$user = Application_Model_User::GetCurrentUser();
$userType = $user->getType();
$this->view->headScript()->appendScript("localStorage.setItem( 'user-type', '$userType' );");
$this->view->headScript()->appendScript($this->generateGoogleTagManagerDataLayerJavaScript());
$this->view->headScript()->appendScript(Application_Common_GoogleAnalytics::generateGoogleTagManagerDataLayerJavaScript());
$this->view->headScript()->appendFile($baseUrl.'js/contextmenu/jquery.contextMenu.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'js/datatables/js/jquery.dataTables.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
@ -367,104 +367,5 @@ class ShowbuilderController extends Zend_Controller_Action
throw new Exception("this controller is/was a no-op please fix your
code");
}
/** Returns a string containing the JavaScript code to pass some billing account info
* into Google Tag Manager / Google Analytics, so we can track things like the plan type.
*/
private static function generateGoogleTagManagerDataLayerJavaScript()
{
$code = "";
try
{
$accessKey = $_SERVER["WHMCS_ACCESS_KEY"];
$username = $_SERVER["WHMCS_USERNAME"];
$password = $_SERVER["WHMCS_PASSWORD"];
$url = "https://account.sourcefabric.com/includes/api.php?accesskey=" . $accessKey; # URL to WHMCS API file goes here
$postfields = array();
$postfields["username"] = $username;
$postfields["password"] = md5($password);
$postfields["action"] = "getclientsdetails";
$postfields["stats"] = true;
$postfields["clientid"] = Application_Model_Preference::GetClientId();
$postfields["responsetype"] = "json";
$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); // WHMCS IP whitelist doesn't support IPv6
curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Aggressive 5 second timeout
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$jsondata = curl_exec($ch);
if (curl_error($ch)) {
//die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
throw new Exception("WHMCS server down or invalid request.");
}
curl_close($ch);
$arr = json_decode($jsondata); # Decode JSON String
if ($arr->result !== "success") {
Logging::warn("WHMCS API call failed in " . __FUNCTION__);
return;
}
$client = $arr->client;
$stats = $arr->stats;
$currencyCode = $client->currency_code;
//$incomeCents = NumberFormatter::parseCurrency($stats->income, $currencyCode);
$isTrial = true;
if (strpos($stats->income, "0.00") === FALSE) {
$isTrial = false;
}
/*
if ($incomeCents > 0) {
$isTrial = false;
}*/
$plan = Application_Model_Preference::GetPlanLevel();
$country = $client->country;
$postcode = $client->postcode;
//Figure out how long the customer has been around using a mega hack.
//(I'm avoiding another round trip to WHMCS for now...)
//We calculate it based on the trial end date...
$trialEndDateStr = Application_Model_Preference::GetTrialEndingDate();
if ($trialEndDateStr == '') {
$accountDuration = 0;
} else {
$today = new DateTime();
$trialEndDate = new DateTime($trialEndDateStr);
$trialDuration = new DateInterval("P30D"); //30 day trial duration
$accountCreationDate = $trialEndDate->sub($trialDuration);
$interval = $today->diff($accountCreationDate);
$accountDuration = $interval->days;
}
$code = "$( document ).ready(function() {
dataLayer.push({
'ZipCode': '" . $postcode . "',
'UserID': '" . $client->id . "',
'Customer': 'Customer',
'PlanType': '" . $plan . "',
'Trial': '" . $isTrial . "',
'Country': '" . $country . "',
'AccountDuration': '" . strval($accountDuration) . "'
});
});";
}
catch (Exception $e)
{
return "";
}
return $code;
}
}

View File

@ -0,0 +1,48 @@
<?php
class ThankYouController extends Zend_Controller_Action
{
public function indexAction()
{
//Variable for the template (thank-you/index.phtml)
$this->view->stationUrl = Application_Common_HTTPHelper::getStationUrl();
$this->view->conversionUrl = Application_Common_HTTPHelper::getStationUrl() . 'thank-you/confirm-conversion';
$this->view->gaEventTrackingJsCode = ""; //Google Analytics event tracking code that logs an event.
// Embed the Google Analytics conversion tracking code if the
// user is a super admin and old plan level is set to trial.
if (Application_Common_GoogleAnalytics::didPaidConversionOccur($this->getRequest())) {
$this->view->gaEventTrackingJsCode = Application_Common_GoogleAnalytics::generateConversionTrackingJavaScript();
}
$csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
$csrf_element = new Zend_Form_Element_Hidden('csrf');
$csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label');
$csrf_form = new Zend_Form();
$csrf_form->addElement($csrf_element);
$this->view->form = $csrf_form;
}
/** Confirm that a conversion was tracked. */
public function confirmConversionAction()
{
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$current_namespace = new Zend_Session_Namespace('csrf_namespace');
$observed_csrf_token = $this->_getParam('csrf_token');
$expected_csrf_token = $current_namespace->authtoken;
if($observed_csrf_token != $expected_csrf_token) {
Logging::info("Invalid CSRF token");
return;
}
if ($this->getRequest()->isPost()) {
Logging::info("Goal conversion from trial to paid.");
// Clear old plan level so we prevent duplicate events.
// This should only be called from AJAX. See thank-you/index.phtml
Application_Model_Preference::ClearOldPlanLevel();
}
}
}

View File

@ -20,7 +20,8 @@ class UpgradeController extends Zend_Controller_Action
array_push($upgraders, new AirtimeUpgrader259());
array_push($upgraders, new AirtimeUpgrader2510());
array_push($upgraders, new AirtimeUpgrader2511());
array_push($upgraders, new AirtimeUpgrader2512());
$didWePerformAnUpgrade = false;
try
{

View File

@ -0,0 +1,21 @@
<?php
class Zend_Controller_Plugin_ConversionTracking extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
//If user is a super admin and old plan level is set to trial....
if (Application_Common_GoogleAnalytics::didPaidConversionOccur($request))
{
//Redirect to Thank you page, unless the request was already going there...
if ($request->getControllerName() != 'thank-you')
{
$request->setModuleName('default')
->setControllerName('thank-you')
->setActionName('index')
->setDispatched(true);
}
}
}
}

View File

@ -0,0 +1,2 @@
ALTER TABLE cc_show ALTER COLUMN description TYPE varchar(8192);
ALTER TABLE cc_show_instances ALTER COLUMN description TYPE varchar(8192);

View File

@ -21,7 +21,6 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
<?php echo $this->partial('partialviews/trialBox.phtml', array("is_trial"=>$this->isTrial(), "trial_remain"=> $this->trialRemaining())) ?>
<div id="Panel">
<div class="logo"></div>
<?php echo $this->versionNotify();
$sss = $this->SourceSwitchStatus();
$scs = $this->SourceConnectionStatus();
@ -30,17 +29,21 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
"scheduled_play_switch"=>$sss['scheduled_play'])) ?>
<?php $partial = array('menu.phtml', 'default');
$this->navigation()->menu()->setPartial($partial); ?>
<div class="personal-block solo">
<ul>
<li>
<!-- <span class="trial-box-button"><a title="Billing" href=<?php echo $baseUrl . 'billing/upgrade'?>>Upgrade</a></span>&nbsp;-->
<a id="current-user" href=<?php echo $baseUrl . "User/edit-user"?>><span class="name"><?php echo $this->escape($this->loggedInAs()); ?></span></a>
| <a href=<?php echo $baseUrl . "Login/logout"?>><?php echo _("Logout")?></a>
</li>
</ul>
</div>
<div id="nav">
<div class="logo"></div>
<div class="personal-block solo">
<ol>
<li>
<!-- <span class="trial-box-button"><a title="Billing" href=<?php echo $baseUrl . 'billing/upgrade'?>>Upgrade</a></span>&nbsp;-->
<a id="current-user" href=<?php echo $baseUrl . "User/edit-user"?>><span class="name"><?php echo $this->escape($this->loggedInAs()); ?></span></a>
| <a href=<?php echo $baseUrl . "Login/logout"?>><?php echo _("Logout")?></a>
</li>
</ol>
</div>
<?php echo $this->navigation()->menu() ?>
<?php echo $this->navigation()->menu() ?>
<div style="clear:both;"></div>
</div>
</div>
<div class="wrapper" id="content"><?php echo $this->layout()->content ?></div>

View File

@ -138,7 +138,9 @@ class Logging {
switch($err['type'])
{
case E_ERROR:
case E_WARNING:
case E_PARSE:
case E_NOTICE:
case E_CORE_ERROR:
case E_CORE_WARNING:
case E_COMPILE_ERROR:

View File

@ -824,7 +824,10 @@ class Application_Model_Preference
public static function SetPlanLevel($plan)
{
$oldPlanLevel = self::GetPlanLevel();
self::setValue("plan_level", $plan);
//We save the old plan level temporarily to facilitate conversion tracking
self::setValue("old_plan_level", $oldPlanLevel);
}
public static function GetPlanLevel()
@ -837,6 +840,19 @@ class Application_Model_Preference
return $plan;
}
public static function GetOldPlanLevel()
{
$oldPlan = self::getValue("old_plan_level");
return $oldPlan;
}
/** Clearing the old plan level indicates a change in your plan has been tracked (Google Analytics) */
public static function ClearOldPlanLevel()
{
self::setValue("old_plan_level", '');
}
public static function SetTrialEndingDate($date)
{
self::setValue("trial_end_date", $date);

View File

@ -984,15 +984,19 @@ SQL;
} else {
Logging::info("Moving file $audio_file to $audio_stor");
//Ensure we have permissions to overwrite the file in stor, in case it already exists.
if (file_exists($audio_stor)) {
chmod($audio_stor, 0644);
}
// Martin K.: changed to rename: Much less load + quicker since this is
// an atomic operation
if (@rename($audio_file, $audio_stor) === false) {
if (rename($audio_file, $audio_stor) === false) {
//something went wrong likely there wasn't enough space in .
//the audio_stor to move the file too warn the user that .
//the file wasn't uploaded and they should check if there .
//is enough disk space .
unlink($audio_file); //remove the file after failed rename
//unlink($id_file); // Also remove the identifier file
throw new Exception("The file was not uploaded, this error can occur if the computer "
. "hard drive does not have enough disk space or the stor "

View File

@ -69,6 +69,15 @@ class Application_Model_User
return $result;
}
public function isSourcefabricAdmin()
{
$username = $this->getLogin();
if ($username == "sourcefabric_admin") {
return true;
}
return false;
}
// TODO : refactor code to only accept arrays for isUserType and
// simplify code even further
public function isUserType($type)

View File

@ -95,9 +95,10 @@ class CcFiles extends BaseCcFiles {
try {
self::createAndImport($fileArray, $tempFilePath, $originalFilename);
} catch (Exception $e)
{
@unlink($tempFilePath);
} catch (Exception $e) {
if (file_exists($tempFilePath)) {
unlink($tempFilePath);
}
throw $e;
}
}

View File

@ -124,6 +124,7 @@ class Rest_MediaController extends Zend_Rest_Controller
catch (Exception $e) {
$this->unknownErrorResponse();
Logging::error($e->getMessage());
throw $e;
}
}

View File

@ -38,14 +38,17 @@ abstract class AirtimeUpgrader
//create a temporary maintenance notification file
//when this file is on the server, zend framework redirects all
//requests to the maintenance page and sets a 503 response code
/* DISABLED because this does not work correctly
$this->maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt";
$file = fopen($this->maintenanceFile, 'w');
fclose($file);
*/
} else {
//delete maintenance.txt to give users access back to Airtime
/* DISABLED because this does not work correctly
if ($this->maintenanceFile) {
unlink($this->maintenanceFile);
}
}*/
}
}
@ -385,3 +388,52 @@ class AirtimeUpgrader2511 extends AirtimeUpgrader
}
}
class AirtimeUpgrader2512 extends AirtimeUpgrader
{
protected function getSupportedVersions() {
return array (
'2.5.10',
'2.5.11'
);
}
public function getNewVersion() {
return '2.5.12';
}
public function upgrade($dir = __DIR__) {
Cache::clear();
assert($this->checkIfUpgradeSupported());
$newVersion = $this->getNewVersion();
try {
$this->toggleMaintenanceScreen(true);
Cache::clear();
// Begin upgrade
$airtimeConf = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : "/etc/airtime/airtime.conf";
$values = parse_ini_file($airtimeConf, true);
$username = $values['database']['dbuser'];
$password = $values['database']['dbpass'];
$host = $values['database']['host'];
$database = $values['database']['dbname'];
passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/upgrade_sql/airtime_"
.$this->getNewVersion()."/upgrade.sql $database 2>&1 | grep -v -E \"will create implicit sequence|will create implicit index\"");
Application_Model_Preference::SetAirtimeVersion($newVersion);
Cache::clear();
$this->toggleMaintenanceScreen(false);
} catch(Exception $e) {
$this->toggleMaintenanceScreen(false);
throw $e;
}
}
public function downgrade() {
}
}

View File

@ -1,4 +1,4 @@
<ul id="nav">
<ol id="navlist">
<?php foreach ($this->container as $page) : ?>
<?php if($this->navigation()->accept($page)) : ?>
<li class="top <?php if($page->isActive(true)){echo 'active';} ?>">
@ -29,4 +29,4 @@
</li>
<?php endif; ?>
<?php endforeach; ?>
</ul>
</ol>

View File

@ -0,0 +1,20 @@
<script type="text/javascript">
$(document).ready(function() {
<?php if ($this->gaEventTrackingJsCode != "") {
echo($this->gaEventTrackingJsCode);
?>
jQuery.post("<?=$this->conversionUrl?>", { "csrf_token" : $("#csrf").attr('value')},
function( data ) {});
<?php }; //endif ?>
});
</script>
<?php echo $this->form->getElement('csrf') ?>
<div class="ui-widget ui-widget-content block-shadow clearfix padded-strong thankyou-panel">
<center>
<div class="logobox" style="margin-left: 32px;"></div>
<h2><?php echo _pro("Thank you!")?></h2>
<h3><?php echo _pro("Your station has been upgraded successfully.")?></h3>
<p><a href="<?=$this->stationUrl?>"><?php echo _pro("Return to Airtime")?></a></p>
</center>
</div>

View File

@ -139,7 +139,7 @@
<column name="name" phpName="DbName" type="VARCHAR" size="255" required="true" defaultValue=""/>
<column name="url" phpName="DbUrl" type="VARCHAR" size="255" required="false" defaultValue=""/>
<column name="genre" phpName="DbGenre" type="VARCHAR" size="255" required="false" defaultValue=""/>
<column name="description" phpName="DbDescription" type="VARCHAR" size="512" required="false"/>
<column name="description" phpName="DbDescription" type="VARCHAR" size="8192" required="false"/>
<column name="color" phpName="DbColor" type="VARCHAR" size="6" required="false"/>
<column name="background_color" phpName="DbBackgroundColor" type="VARCHAR" size="6" required="false"/>
<column name="live_stream_using_airtime_auth" phpName="DbLiveStreamUsingAirtimeAuth" type="BOOLEAN" required="false" defaultValue="false"/>
@ -156,7 +156,7 @@
</table>
<table name="cc_show_instances" phpName="CcShowInstances">
<column name="id" phpName="DbId" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/>
<column name="description" phpName="DbDescription" type="VARCHAR" size="512" required="false" defaultValue=""/>
<column name="description" phpName="DbDescription" type="VARCHAR" size="8192" required="false" defaultValue=""/>
<column name="starts" phpName="DbStarts" type="TIMESTAMP" required="true"/>
<column name="ends" phpName="DbEnds" type="TIMESTAMP" required="true"/>
<column name="show_id" phpName="DbShowId" type="INTEGER" required="true"/>

View File

@ -149,7 +149,7 @@ CREATE TABLE "cc_show"
"name" VARCHAR(255) DEFAULT '' NOT NULL,
"url" VARCHAR(255) DEFAULT '',
"genre" VARCHAR(255) DEFAULT '',
"description" VARCHAR(512),
"description" VARCHAR(8192),
"color" VARCHAR(6),
"background_color" VARCHAR(6),
"live_stream_using_airtime_auth" BOOLEAN DEFAULT 'f',
@ -171,7 +171,7 @@ DROP TABLE IF EXISTS "cc_show_instances" CASCADE;
CREATE TABLE "cc_show_instances"
(
"id" serial NOT NULL,
"description" VARCHAR(512) DEFAULT '',
"description" VARCHAR(8192) DEFAULT '',
"starts" TIMESTAMP NOT NULL,
"ends" TIMESTAMP NOT NULL,
"show_id" INTEGER NOT NULL,

View File

@ -463,8 +463,10 @@ class AMQPConnection extends AbstractChannel
{
debug_msg("closing socket");
}
@fclose($this->sock);
if (is_resource($this->sock)) {
@fclose($this->sock);
}
$this->sock = NULL;
}
}

View File

@ -300,13 +300,12 @@
.personal-block.solo {
position: absolute;
right: 145px;
top: 104px;
width: auto;
z-index: 1000;
height:auto;
margin:0;
width: auto;
height:auto;
margin: 0 10px 0 0;
}
.personal-block.solo ol {
margin-top: 6px;
}
.time-info-block.pull-right {
margin-right:0;

View File

@ -48,14 +48,12 @@ select {
}
.logo {
position:absolute;
right:20px;
top:104px;
background:transparent url(images/airtime_logo.png) no-repeat 0 0;
height:35px;
width:66px;
z-index:1000;
display:block;
background: transparent url(images/airtime_logo.png) no-repeat 0 0;
height: 35px;
width: 66px;
float: right;
padding: 0 5px 0 10px;
margin-top: -5px;
}
/* Version Notification Starts*/
@ -286,8 +284,74 @@ select {
background:url(images/masterpanel_spacer.png) no-repeat right 0;
}
.time-info-block {
padding:0 14px 0 2px;
min-width:105px;
position: absolute;
top: 0;
right: 0;
}
#navlist {
padding: 0;
margin: 0;
}
#nav li.top {
/*float: none;*/
}
@media screen and (max-width: 1200px) {
.now-playing-block {
width: 30%;
}
.show-block {
width: 25%;
}
}
@media screen and (max-width: 920px) {
.now-playing-block {
width: 50%;
}
.show-block {
display: none;
}
.personal-block.solo {
right: 10px !important;
}
}
@media screen and (max-width: 810px) {
.now-playing-block {
width: 40%;
}
}
@media screen and (max-width: 863px) {
#nav {
height: inherit;
overflow-y: visible;
}
}
@media screen and (max-width: 680px) {
.now-playing-block {
display: none;
}
#nav li.top {
display: -webkit-flex;
width: 110px;
}
.personal-block.solo {
float: none;
text-align: left;
}
.personal-block.solo ol {
padding-left: 12px;
}
.logo {
float: none;
margin-left: 12px;
}
}
@media screen and (max-width: 380px) {
.time-info-block {
display: none;
}
.on-air-block {
margin: 0;
}
}
.time-info-block ul {
margin:0;
@ -3141,3 +3205,15 @@ dd .stream-status {
.quota-reached {
font-size: 14px !important;
}
.thankyou-panel
{
width: 400px;
margin: 0 auto;
margin-bottom: 30px;
}
.thankyou-panel h3
{
color: #222;
}

View File

@ -82,7 +82,7 @@ function closeAddShowForm(event) {
redrawAddShowForm($el, json.form);
});
makeAddShowButton();
}
@ -742,7 +742,7 @@ function setAddShowEvents(form) {
image = new FormData();
image.append('file', $('#add_show_logo')[0].files[0]);
}
$.ajax({
url: action,
data: {format: "json", data: data, hosts: hosts, days: days},
@ -784,6 +784,7 @@ function setAddShowEvents(form) {
} else {
redrawAddShowForm($addShowForm, json.newForm);
scheduleRefetchEvents(json);
$addShowForm.hide();
}
}
});

View File

@ -129,6 +129,7 @@ def send_http_request(picklable_request, retry_queue):
retry_queue.append(picklable_request) # Retry it later
except Exception as e:
logging.error("HTTP request failed with unhandled exception. %s" % str(e))
logging.error(traceback.format_exc())
# Don't put the request into the retry queue, just give up on this one.
# I'm doing this to protect against us getting some pathological request
# that breaks our code. I don't want us pickling data that potentially

View File

@ -2,10 +2,14 @@
post_file() {
#kill process after 30 minutes (360*5=30 minutes)
max_retry=360
max_retry=5
retry_count=0
file_path="${1}"
# Give us write permissions on the file to prevent problems if the user
# uploads a read-only file.
chmod +w "${file_path}"
#We must remove commas because CURL can't upload files with commas in the name
# http://curl.haxx.se/mail/archive-2009-07/0029.html
stripped_file_path=${file_path//','/''}