From 70b409184a7c9ec34b6019ca9c0acee473c04648 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 6 Oct 2014 00:00:42 +0300 Subject: [PATCH 01/11] Version check and news feed messages --- app/controllers/AccountController.php | 15 +----- app/controllers/HomeController.php | 23 ++++++++++ app/controllers/UserController.php | 3 ++ ...4_10_05_141856_track_last_seen_message.php | 46 +++++++++++++++++++ app/database/seeds/PaymentLibrariesSeeder.php | 19 +++++--- app/filters.php | 41 ++++++++++++++--- app/lang/de/texts.php | 2 + app/lang/en/texts.php | 3 +- app/lang/es/texts.php | 2 + app/lang/fr/texts.php | 2 + app/lang/it/texts.php | 3 ++ app/lang/lt/texts.php | 2 + app/lang/nb_NO/texts.php | 2 + app/lang/nl/texts.php | 2 + app/lang/pt_BR/texts.php | 2 + app/libraries/utils.php | 34 ++++++++++++++ app/models/Account.php | 6 ++- app/routes.php | 14 ++++-- app/views/header.blade.php | 15 +++++- app/views/reports/d3.blade.php | 16 +++---- 20 files changed, 212 insertions(+), 40 deletions(-) create mode 100644 app/database/migrations/2014_10_05_141856_track_last_seen_message.php diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index a531cab6d183..40e8af6e76ca 100755 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -36,20 +36,9 @@ class AccountController extends \BaseController { public function update() { if (!Utils::isNinja()) { - // populate migrations if the application was initially setup using database.sql - $migrations = DB::table('migrations')->get(); - if (Schema::hasTable('accounts') && count($migrations) == 0) { - $migrations = ['2013_11_05_180133_confide_setup_users_table', '2013_11_28_195703_setup_countries_table', '2014_02_13_151500_add_cascase_drops', '2014_02_19_151817_add_support_for_invoice_designs', '2014_03_03_155556_add_phone_to_account', '2014_03_19_201454_add_language_support', '2014_03_20_200300_create_payment_libraries', '2014_03_23_051736_enable_forcing_jspdf', '2014_03_25_102200_add_sort_and_recommended_to_gateways', '2014_04_03_191105_add_pro_plan', '2014_04_17_100523_add_remember_token', '2014_04_17_145108_add_custom_fields', '2014_04_23_170909_add_products_settings', '2014_04_29_174315_add_advanced_settings', '2014_05_17_175626_add_quotes', '2014_06_17_131940_add_accepted_credit_cards_to_account_gateways', '2014_07_13_142654_one_click_install', '2014_07_17_205900_support_hiding_quantity', '2014_07_24_171214_add_zapier_support']; - foreach ($migrations as $migration) { - DB::table('migrations')->insert([ - 'migration' => $migration, - 'batch' => 1 - ]); - } - } - try { - Artisan::call('migrate'); + Artisan::call('migrate'); + Cache::flush(); } catch (Exception $e) { Response::make($e->getMessage(), 500); } diff --git a/app/controllers/HomeController.php b/app/controllers/HomeController.php index b9415d58bfa0..8389a36980b2 100755 --- a/app/controllers/HomeController.php +++ b/app/controllers/HomeController.php @@ -128,6 +128,29 @@ class HomeController extends BaseController { } } + public function newsFeed($userType, $version) + { + $response = Utils::getNewsFeedResponse($userType); + + return Response::json($response); + } + + public function hideMessage() + { + if (Auth::check() && Session::has('news_feed_id')) { + $newsFeedId = Session::get('news_feed_id'); + if ($newsFeedId != NEW_VERSION_AVAILABLE && $newsFeedId > Auth::user()->news_feed_id) { + $user = Auth::user(); + $user->news_feed_id = $newsFeedId; + $user->save(); + } + + Session::forget('news_feed_message'); + } + + return 'success'; + } + public function logError() { return Utils::logError(Input::get('error'), 'JavaScript'); diff --git a/app/controllers/UserController.php b/app/controllers/UserController.php index a62c30e5deed..bfe710c12a90 100755 --- a/app/controllers/UserController.php +++ b/app/controllers/UserController.php @@ -463,6 +463,9 @@ class UserController extends BaseController { } } + Session::forget('news_feed_id'); + Session::forget('news_feed_message'); + Confide::logout(); return Redirect::to('/')->with('clearGuestKey', true); diff --git a/app/database/migrations/2014_10_05_141856_track_last_seen_message.php b/app/database/migrations/2014_10_05_141856_track_last_seen_message.php new file mode 100644 index 000000000000..7446782a6ac3 --- /dev/null +++ b/app/database/migrations/2014_10_05_141856_track_last_seen_message.php @@ -0,0 +1,46 @@ +unsignedInteger('news_feed_id')->nullable(); + }); + + if (DB::table('payment_libraries')->count() > 0) { + DB::table('gateways')->update(['recommended' => 0]); + DB::table('gateways')->insert([ + 'name' => 'moolah', + 'provider' => 'AuthorizeNet_AIM', + 'sort_order' => 1, + 'recommended' => 1, + 'site_url' => 'https://invoiceninja.mymoolah.com/', + 'payment_library_id' => 1 + ]); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function($table) + { + $table->dropColumn('news_feed_id'); + }); + } + +} diff --git a/app/database/seeds/PaymentLibrariesSeeder.php b/app/database/seeds/PaymentLibrariesSeeder.php index 24a958228eef..b9dbf578be9d 100644 --- a/app/database/seeds/PaymentLibrariesSeeder.php +++ b/app/database/seeds/PaymentLibrariesSeeder.php @@ -17,13 +17,18 @@ class PaymentLibrariesSeeder extends Seeder Gateway::create($gateway); } - Gateway::create([ - 'name' => 'moolah', - 'provider' => 'AuthorizeNet_AIM', - 'sort_order' => 1, - 'recommended' => 1, - 'site_url' => 'https://invoiceninja.mymoolah.com/', - ]); + // check that moolah exists + if (!DB::table('gateways')->where('name', '=', 'moolah')->get()) { + DB::table('gateways')->update(['recommended' => 0]); + DB::table('gateways')->insert([ + 'name' => 'moolah', + 'provider' => 'AuthorizeNet_AIM', + 'sort_order' => 1, + 'recommended' => 1, + 'site_url' => 'https://invoiceninja.mymoolah.com/', + 'payment_library_id' => 1 + ]); + } /* $updateProviders = array( diff --git a/app/filters.php b/app/filters.php index 80e02cdf72db..9c252974fafb 100755 --- a/app/filters.php +++ b/app/filters.php @@ -13,12 +13,6 @@ App::before(function($request) { - if (Auth::check()) - { - $count = Session::get(SESSION_COUNTER, 0); - Session::put(SESSION_COUNTER, ++$count); - } - if (App::environment() == ENV_PRODUCTION) { if (!Request::secure()) @@ -27,6 +21,41 @@ App::before(function($request) } } + if (Auth::check()) + { + $count = Session::get(SESSION_COUNTER, 0); + Session::put(SESSION_COUNTER, ++$count); + + // check the application is up to date and for any news feed messages + if (!Utils::startsWith($_SERVER['REQUEST_URI'], '/news_feed') && !Session::has('news_feed_id')) { + $data = false; + if (Utils::isNinja()) { + $data = Utils::getNewsFeedResponse(); + } else { + $file = @file_get_contents(NINJA_URL . '/news_feed/' . Utils::getUserType() . '/' . NINJA_VERSION); + $data = @json_decode($file); + } + if ($data) { + if ($data->version != NINJA_VERSION) { + $params = [ + 'user_version' => NINJA_VERSION, + 'latest_version'=> $data->version, + 'releases_link' => link_to(RELEASES_URL, 'Invoice Ninja', ['target' => '_blank']) + ]; + Session::put('news_feed_id', NEW_VERSION_AVAILABLE); + Session::put('news_feed_message', trans('texts.new_version_available', $params)); + } else { + Session::put('news_feed_id', $data->id); + if ($data->message && $data->id > Auth::user()->news_feed_id) { + Session::put('news_feed_message', $data->message); + } + } + } else { + Session::put('news_feed_id', true); + } + } + } + if (Input::has('lang')) { $locale = Input::get('lang'); diff --git a/app/lang/de/texts.php b/app/lang/de/texts.php index c4c44257cf3a..f7ad286a6072 100644 --- a/app/lang/de/texts.php +++ b/app/lang/de/texts.php @@ -422,5 +422,7 @@ return array( 'data_visualizations' => 'Data Visualizations', 'sample_data' => 'Sample data shown', + 'hide' => 'Hide', + 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', ); diff --git a/app/lang/en/texts.php b/app/lang/en/texts.php index f7a2e0295b6b..bccafb083283 100644 --- a/app/lang/en/texts.php +++ b/app/lang/en/texts.php @@ -430,6 +430,7 @@ return array( 'data_visualizations' => 'Data Visualizations', 'sample_data' => 'Sample data shown', - + 'hide' => 'Hide', + 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', ); \ No newline at end of file diff --git a/app/lang/es/texts.php b/app/lang/es/texts.php index 05a63547e30c..668e2abb590b 100644 --- a/app/lang/es/texts.php +++ b/app/lang/es/texts.php @@ -420,5 +420,7 @@ return array( 'data_visualizations' => 'Data Visualizations', 'sample_data' => 'Sample data shown', + 'hide' => 'Hide', + 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', ); diff --git a/app/lang/fr/texts.php b/app/lang/fr/texts.php index 5565e5be70fe..e5cc815f7093 100644 --- a/app/lang/fr/texts.php +++ b/app/lang/fr/texts.php @@ -422,6 +422,8 @@ return array( 'data_visualizations' => 'Data Visualizations', 'sample_data' => 'Sample data shown', + 'hide' => 'Hide', + 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', ); diff --git a/app/lang/it/texts.php b/app/lang/it/texts.php index a2c8ad2dec22..8a6df978935c 100644 --- a/app/lang/it/texts.php +++ b/app/lang/it/texts.php @@ -422,5 +422,8 @@ return array( 'data_visualizations' => 'Data Visualizations', 'sample_data' => 'Sample data shown', + 'hide' => 'Hide', + 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', + ); diff --git a/app/lang/lt/texts.php b/app/lang/lt/texts.php index 9364251271a3..f345dd6dd993 100644 --- a/app/lang/lt/texts.php +++ b/app/lang/lt/texts.php @@ -430,6 +430,8 @@ return array( 'data_visualizations' => 'Data Visualizations', 'sample_data' => 'Sample data shown', + 'hide' => 'Hide', + 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', ); diff --git a/app/lang/nb_NO/texts.php b/app/lang/nb_NO/texts.php index e590a2cb4eda..44b5e0bbc354 100644 --- a/app/lang/nb_NO/texts.php +++ b/app/lang/nb_NO/texts.php @@ -430,6 +430,8 @@ return array( 'data_visualizations' => 'Data Visualizations', 'sample_data' => 'Sample data shown', + 'hide' => 'Hide', + 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', ); \ No newline at end of file diff --git a/app/lang/nl/texts.php b/app/lang/nl/texts.php index f5b3718995e7..319c7ccfea21 100644 --- a/app/lang/nl/texts.php +++ b/app/lang/nl/texts.php @@ -423,6 +423,8 @@ return array( 'data_visualizations' => 'Data Visualizations', 'sample_data' => 'Sample data shown', + 'hide' => 'Hide', + 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', ); diff --git a/app/lang/pt_BR/texts.php b/app/lang/pt_BR/texts.php index 5084cff31f85..0c8b6fd58886 100644 --- a/app/lang/pt_BR/texts.php +++ b/app/lang/pt_BR/texts.php @@ -411,6 +411,8 @@ return array( 'data_visualizations' => 'Data Visualizations', 'sample_data' => 'Sample data shown', + 'hide' => 'Hide', + 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', ); diff --git a/app/libraries/utils.php b/app/libraries/utils.php index 41f10c4222d3..493a9168b7f1 100755 --- a/app/libraries/utils.php +++ b/app/libraries/utils.php @@ -37,6 +37,29 @@ class Utils return Auth::check() && Auth::user()->isPro(); } + public static function getUserType() + { + if (Utils::isNinja()) { + return USER_TYPE_CLOUD_HOST; + } else { + return USER_TYPE_SELF_HOST; + } + } + + public static function getNewsFeedResponse($userType = false) + { + if (!$userType) { + $userType = Utils::getUserType(); + } + + $response = new stdClass; + $response->message = isset($_ENV["{$userType}_MESSAGE"]) ? $_ENV["{$userType}_MESSAGE"] : ''; + $response->id = isset($_ENV["{$userType}_ID"]) ? $_ENV["{$userType}_ID"] : ''; + $response->version = NINJA_VERSION; + + return $response; + } + public static function getProLabel($feature) { if (Auth::check() @@ -535,4 +558,15 @@ class Utils //'X-Rate-Limit-Reset' - The number of seconds left in the current period, ]; } + + public static function startsWith($haystack, $needle) + { + return $needle === "" || strpos($haystack, $needle) === 0; + } + + public static function endsWith($haystack, $needle) + { + return $needle === "" || substr($haystack, -strlen($needle)) === $needle; + } + } \ No newline at end of file diff --git a/app/models/Account.php b/app/models/Account.php index c8327c8d6649..5cfdb4365a9c 100755 --- a/app/models/Account.php +++ b/app/models/Account.php @@ -290,7 +290,11 @@ class Account extends Eloquent foreach ($client->contacts as $contact) { - $contact->setVisible(['public_id']); + $contact->setVisible([ + 'public_id', + 'first_name', + 'last_name', + 'email']); } } diff --git a/app/routes.php b/app/routes.php index 4afaa5980ab5..9f75562d1e58 100755 --- a/app/routes.php +++ b/app/routes.php @@ -36,7 +36,7 @@ Route::post('/contact_submit', 'HomeController@doContactUs'); Route::get('/faq', 'HomeController@showFaq'); Route::get('/features', 'HomeController@showFeatures'); Route::get('/testimonials', 'HomeController@showTestimonials'); -Route::get('/compare-online-invoicing', 'HomeController@showCompare'); +Route::get('/compare-online-invoicing{sites?}', 'HomeController@showCompare'); Route::get('log_error', 'HomeController@logError'); Route::get('invoice_now', 'HomeController@invoiceNow'); @@ -54,7 +54,6 @@ Route::get('claim_license', 'PaymentController@claim_license'); Route::post('signup/validate', 'AccountController@checkEmail'); Route::post('signup/submit', 'AccountController@submitSignup'); - // Confide routes Route::get('login', 'UserController@login'); Route::post('login', 'UserController@do_login'); @@ -65,11 +64,15 @@ Route::get('user/reset/{token?}', 'UserController@reset_password'); Route::post('user/reset', 'UserController@do_reset_password'); Route::get('logout', 'UserController@logout'); +if (Utils::isNinja()) { + Route::get('/news_feed/{user_type}/{version}/', 'HomeController@newsFeed'); +} Route::group(array('before' => 'auth'), function() { Route::get('dashboard', 'DashboardController@index'); Route::get('view_archive/{entity_type}/{visible}', 'AccountController@setTrashVisible'); + Route::get('hide_message', 'HomeController@hideMessage'); Route::get('force_inline_pdf', 'UserController@forcePDFJS'); Route::get('api/users', array('as'=>'api.users', 'uses'=>'UserController@getDatatable')); @@ -236,11 +239,16 @@ define('NINJA_ACCOUNT_KEY', 'zg4ylmzDkdkPOT8yoKQw9LTWaoZJx79h'); define('NINJA_GATEWAY_ID', GATEWAY_AUTHORIZE_NET); define('NINJA_GATEWAY_CONFIG', '{"apiLoginId":"626vWcD5","transactionKey":"4bn26TgL9r4Br4qJ","testMode":"","developerMode":""}'); define('NINJA_URL', 'https://www.invoiceninja.com'); -define('NINJA_VERSION', '1.3.3'); +define('NINJA_VERSION', '1.4.0'); +define('RELEASES_URL', 'https://github.com/hillelcoren/invoice-ninja/releases/'); define('PRO_PLAN_PRICE', 50); define('LICENSE_PRICE', 30.00); +define('USER_TYPE_SELF_HOST', 'SELF_HOST'); +define('USER_TYPE_CLOUD_HOST', 'CLOUD_HOST'); +define('NEW_VERSION_AVAILABLE', 'NEW_VERSION_AVAILABLE'); + /* define('GATEWAY_AMAZON', 30); define('GATEWAY_BLUEPAY', 31); diff --git a/app/views/header.blade.php b/app/views/header.blade.php index 991f6e5a7367..9f374095e0b0 100755 --- a/app/views/header.blade.php +++ b/app/views/header.blade.php @@ -197,7 +197,14 @@ @endif @if (Session::has('message')) -
{{ Session::get('message') }}
+
+ {{ Session::get('message') }} +
+ @elseif (Session::has('news_feed_message')) +
+ {{ Session::get('news_feed_message') }} + {{ trans('texts.hide') }} +
@endif @if (Session::has('error')) @@ -542,6 +549,12 @@ Want something changed? We're {{ link_to('https://github.com/hillelcoren/invoice } @endif + function hideMessage() { + $('.alert-info').fadeOut(); + $.get('/hide_message', function(response) { + console.log('Reponse: %s', response); + }); + } $(function() { $('#search').focus(function(){ diff --git a/app/views/reports/d3.blade.php b/app/views/reports/d3.blade.php index 70099d20bc30..7e0c3b8e7e2f 100644 --- a/app/views/reports/d3.blade.php +++ b/app/views/reports/d3.blade.php @@ -106,16 +106,16 @@ client.displayBalance = +client.balance; client.displayPercent = (+client.paid_to_date / (+client.paid_to_date + +client.balance)).toFixed(2); var oldestInvoice = _.max(client.invoices, function(invoice) { return calculateInvoiceAge(invoice) }); - client.displayAge = oldestInvoice ? calculateInvoiceAge(oldestInvoice) : 0; - }) + client.displayAge = oldestInvoice ? calculateInvoiceAge(oldestInvoice) : -1; + }); _.each(invoices, function(invoice) { invoice.displayName = invoice.invoice_number; invoice.displayTotal = +invoice.amount; invoice.displayBalance = +invoice.balance; - invoice.displayPercent = parseInt((+invoice.amount - +invoice.balance) / +invoice.amount); + invoice.displayPercent = (+invoice.amount - +invoice.balance) / +invoice.amount; invoice.displayAge = calculateInvoiceAge(invoice); - }) + }); _.each(products, function(product) { product.displayName = product.key; @@ -123,7 +123,7 @@ product.displayBalance = product.values.amount - product.values.paid; product.displayPercent = (product.values.paid / product.values.amount).toFixed(2); product.displayAge = product.values.age; - }) + }); /* _.each(clients, function(client) { @@ -210,7 +210,7 @@ d3.select("#tooltipTitle").text(truncate(d.displayName, 18)); d3.select("#tooltipTotal").text(formatMoney(d.displayTotal)); d3.select("#tooltipBalance").text(formatMoney(d.displayBalance)); - d3.select("#tooltipAge").text(pluralize('? day', parseInt(d.displayAge))); + d3.select("#tooltipAge").text(pluralize('? day', parseInt(Math.max(0, d.displayAge)))); if (groupBy == "products" || !d.public_id) { d3.select("#tooltip a").classed("hidden", true); @@ -260,7 +260,7 @@ .transition() .duration(1000) .style("fill", function(d, i) { - return d.displayAge ? color(d.displayAge) : 'grey'; + return d.displayAge == -1 ? 'grey' : color(d.displayAge); }); selection.exit().remove(); @@ -281,7 +281,7 @@ function calculateInvoiceAge(invoice) { if (!invoice || invoice.invoice_status_id == 5) { - return 0; + return -1; } return parseInt((new Date().getTime() - Date.parse(invoice.created_at)) / (1000*60*60*24)); From d5ac64bf654b8b7fbc1663b83f04c2fc19d87e33 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 6 Oct 2014 00:13:54 +0300 Subject: [PATCH 02/11] Fixed typo --- app/lang/en/texts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lang/en/texts.php b/app/lang/en/texts.php index bccafb083283..a6d3b9f495e5 100644 --- a/app/lang/en/texts.php +++ b/app/lang/en/texts.php @@ -422,7 +422,7 @@ return array( 'confirm_email_invoice' => 'Are you sure you want to email this invoice?', 'confirm_email_quote' => 'Are you sure you want to email this quote?', - 'confirm_recurring_email_invoice' => 'Recurring is enabled,re you sure you want this invoice emailed?', + 'confirm_recurring_email_invoice' => 'Recurring is enabled, are you sure you want this invoice emailed?', 'cancel_account' => 'Cancel Account', 'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.', From e8b5317f2e5571b131f3c6460b2932f721e64acd Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 6 Oct 2014 00:31:14 +0300 Subject: [PATCH 03/11] Added d3 to js folder --- app/views/reports/d3.blade.php | 2 +- public/js/d3.min.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 public/js/d3.min.js diff --git a/app/views/reports/d3.blade.php b/app/views/reports/d3.blade.php index 7e0c3b8e7e2f..9e1199c93db1 100644 --- a/app/views/reports/d3.blade.php +++ b/app/views/reports/d3.blade.php @@ -3,7 +3,7 @@ @section('head') @parent - + @@ -35,8 +42,6 @@ @section('body') -

 

-