1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-19 16:01:34 +02:00
Conflicts:
	composer.lock
This commit is contained in:
Troels Liebe Bentsen 2014-10-14 23:48:59 +02:00
commit 8ca8cc91b1
44 changed files with 1762 additions and 2436 deletions

View File

@ -39,6 +39,16 @@ module.exports = function(grunt) {
dest: 'public/built.js',
nonull: true
},
js_public: {
src: [
'public/js/simpleexpand.js',
'public/js/valign.js',
'public/js/bootstrap.min.js',
'public/js/simpleexpand.js',
],
dest: 'public/js/built.public.js',
nonull: true
},
css: {
src: [
'public/vendor/bootstrap/dist/css/bootstrap.min.css',

View File

@ -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');
Cache::flush();
} catch (Exception $e) {
Response::make($e->getMessage(), 500);
}
@ -262,6 +251,31 @@ class AccountController extends \BaseController {
'feature' => $subSection
];
if ($subSection == ACCOUNT_INVOICE_DESIGN)
{
$invoice = new stdClass();
$client = new stdClass();
$invoiceItem = new stdClass();
$client->name = 'Sample Client';
$invoice->invoice_number = Auth::user()->account->getNextInvoiceNumber();
$invoice->invoice_date = date_create()->format('Y-m-d');
$invoice->account = Auth::user()->account;
$invoice->amount = $invoice->balance = 100;
$invoiceItem->cost = 100;
$invoiceItem->qty = 1;
$invoiceItem->notes = 'Notes';
$invoiceItem->product_key = 'Item';
$invoice->client = $client;
$invoice->invoice_items = [$invoiceItem];
$data['invoice'] = $invoice;
$data['invoiceDesigns'] = InvoiceDesign::remember(DEFAULT_QUERY_CACHE)->orderBy('id')->get();
}
return View::make("accounts.{$subSection}", $data);
}
else if ($section == ACCOUNT_PRODUCTS)
@ -302,9 +316,9 @@ class AccountController extends \BaseController {
}
else if ($section == ACCOUNT_ADVANCED_SETTINGS)
{
if ($subSection == ACCOUNT_CUSTOM_FIELDS)
if ($subSection == ACCOUNT_INVOICE_SETTINGS)
{
return AccountController::saveCustomFields();
return AccountController::saveInvoiceSettings();
}
else if ($subSection == ACCOUNT_INVOICE_DESIGN)
{
@ -329,11 +343,12 @@ class AccountController extends \BaseController {
return Redirect::to('company/products');
}
private function saveCustomFields()
private function saveInvoiceSettings()
{
if (Auth::user()->account->isPro())
{
$account = Auth::user()->account;
$account->custom_label1 = trim(Input::get('custom_label1'));
$account->custom_value1 = trim(Input::get('custom_value1'));
$account->custom_label2 = trim(Input::get('custom_label2'));
@ -344,12 +359,26 @@ class AccountController extends \BaseController {
$account->custom_invoice_label2 = trim(Input::get('custom_invoice_label2'));
$account->custom_invoice_taxes1 = Input::get('custom_invoice_taxes1') ? true : false;
$account->custom_invoice_taxes2 = Input::get('custom_invoice_taxes2') ? true : false;
$account->save();
Session::flash('message', trans('texts.updated_settings'));
$account->invoice_number_prefix = Input::get('invoice_number_prefix');
$account->invoice_number_counter = Input::get('invoice_number_counter');
$account->quote_number_prefix = Input::get('quote_number_prefix');
$account->share_counter = Input::get('share_counter') ? true : false;
if (!$account->share_counter) {
$account->quote_number_counter = Input::get('quote_number_counter');
}
if (!$account->share_counter && $account->invoice_number_prefix == $account->quote_number_prefix) {
Session::flash('error', trans('texts.invalid_counter'));
return Redirect::to('company/advanced_settings/invoice_settings')->withInput();
} else {
$account->save();
Session::flash('message', trans('texts.updated_settings'));
}
}
return Redirect::to('company/advanced_settings/custom_fields');
return Redirect::to('company/advanced_settings/invoice_settings');
}
private function saveInvoiceDesign()
@ -359,8 +388,9 @@ class AccountController extends \BaseController {
$account = Auth::user()->account;
$account->hide_quantity = Input::get('hide_quantity') ? true : false;
$account->hide_paid_to_date = Input::get('hide_paid_to_date') ? true : false;
$account->primary_color = Input::get('primary_color');// ? Input::get('primary_color') : null;
$account->secondary_color = Input::get('secondary_color');// ? Input::get('secondary_color') : null;
$account->primary_color = Input::get('primary_color');
$account->secondary_color = Input::get('secondary_color');
$account->invoice_design_id = Input::get('invoice_design_id');
$account->save();
Session::flash('message', trans('texts.updated_settings'));

View File

@ -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');

View File

@ -104,7 +104,7 @@ class InvoiceController extends \BaseController {
}
}
$invoice->load('user', 'invoice_items', 'account.country', 'client.contacts', 'client.country');
$invoice->load('user', 'invoice_items', 'invoice_design', 'account.country', 'client.contacts', 'client.country');
$client = $invoice->client;
@ -151,7 +151,7 @@ class InvoiceController extends \BaseController {
if ($clone)
{
$invoice->id = null;
$invoice->invoice_number = Auth::user()->account->getNextInvoiceNumber();
$invoice->invoice_number = Auth::user()->account->getNextInvoiceNumber($invoice->is_quote);
$invoice->balance = $invoice->amount;
$method = 'POST';
$url = "{$entityType}s";
@ -244,7 +244,6 @@ class InvoiceController extends \BaseController {
'paymentTerms' => PaymentTerm::remember(DEFAULT_QUERY_CACHE)->orderBy('num_days')->get(['name', 'num_days']),
'industries' => Industry::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(),
'invoiceDesigns' => InvoiceDesign::remember(DEFAULT_QUERY_CACHE)->orderBy('id')->get(),
'invoiceLabels' => Auth::user()->account->getInvoiceLabels(),
'frequencies' => array(
1 => 'Weekly',
2 => 'Two weeks',
@ -272,7 +271,7 @@ class InvoiceController extends \BaseController {
$action = Input::get('action');
$entityType = Input::get('entityType');
if ($action == 'archive' || $action == 'delete')
if ($action == 'archive' || $action == 'delete' || $action == 'mark')
{
return InvoiceController::bulk($entityType);
}
@ -414,12 +413,14 @@ class InvoiceController extends \BaseController {
public function bulk($entityType = ENTITY_INVOICE)
{
$action = Input::get('action');
$statusId = Input::get('statusId');
$ids = Input::get('id') ? Input::get('id') : Input::get('ids');
$count = $this->invoiceRepo->bulk($ids, $action);
$count = $this->invoiceRepo->bulk($ids, $action, $statusId);
if ($count > 0)
{
$message = Utils::pluralize("{$action}d_{$entityType}", $count);
$key = $action == 'mark' ? "updated_{$entityType}" : "{$action}d_{$entityType}";
$message = Utils::pluralize($key, $count);
Session::flash('message', $message);
}

View File

@ -60,7 +60,7 @@ class QuoteController extends \BaseController {
}
$client = null;
$invoiceNumber = Auth::user()->account->getNextInvoiceNumber();
$invoiceNumber = Auth::user()->account->getNextInvoiceNumber(true);
$account = Account::with('country')->findOrFail(Auth::user()->account_id);
if ($clientPublicId)

View File

@ -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);

View File

@ -0,0 +1,46 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class TrackLastSeenMessage extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function($table)
{
$table->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');
});
}
}

View File

@ -0,0 +1,515 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddInvoiceDesignTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('invoice_designs', function($table)
{
$table->text('javascript')->nullable();
});
Schema::table('accounts', function($table)
{
$table->text('invoice_design')->nullable();
});
DB::table('invoice_designs')->where('id', 1)->update([
'javascript' => "var GlobalY=0;//Y position of line at current page
var client = invoice.client;
var account = invoice.account;
var currencyId = client.currency_id;
layout.headerRight = 550;
layout.rowHeight = 15;
doc.setFontSize(9);
if (invoice.image)
{
var left = layout.headerRight - invoice.imageWidth;
doc.addImage(invoice.image, 'JPEG', layout.marginLeft, 30);
}
if (!invoice.is_pro && logoImages.imageLogo1)
{
pageHeight=820;
y=pageHeight-logoImages.imageLogoHeight1;
doc.addImage(logoImages.imageLogo1, 'JPEG', layout.marginLeft, y, logoImages.imageLogoWidth1, logoImages.imageLogoHeight1);
}
doc.setFontSize(9);
SetPdfColor('LightBlue', doc, 'primary');
displayAccount(doc, invoice, 220, layout.accountTop, layout);
SetPdfColor('LightBlue', doc, 'primary');
doc.setFontSize('11');
doc.text(50, layout.headerTop, (invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice).toUpperCase());
SetPdfColor('Black',doc); //set black color
doc.setFontSize(9);
var invoiceHeight = displayInvoice(doc, invoice, 50, 170, layout);
var clientHeight = displayClient(doc, invoice, 220, 170, layout);
var detailsHeight = Math.max(invoiceHeight, clientHeight);
layout.tableTop = Math.max(layout.tableTop, layout.headerTop + detailsHeight + (3 * layout.rowHeight));
doc.setLineWidth(0.3);
doc.setDrawColor(200,200,200);
doc.line(layout.marginLeft - layout.tablePadding, layout.headerTop + 6, layout.marginRight + layout.tablePadding, layout.headerTop + 6);
doc.line(layout.marginLeft - layout.tablePadding, layout.headerTop + detailsHeight + 14, layout.marginRight + layout.tablePadding, layout.headerTop + detailsHeight + 14);
doc.setFontSize(10);
doc.setFontType('bold');
displayInvoiceHeader(doc, invoice, layout);
var y = displayInvoiceItems(doc, invoice, layout);
doc.setFontSize(9);
doc.setFontType('bold');
GlobalY=GlobalY+25;
doc.setLineWidth(0.3);
doc.setDrawColor(241,241,241);
doc.setFillColor(241,241,241);
var x1 = layout.marginLeft - 12;
var y1 = GlobalY-layout.tablePadding;
var w2 = 510 + 24;
var h2 = doc.internal.getFontSize()*3+layout.tablePadding*2;
if (invoice.discount) {
h2 += doc.internal.getFontSize()*2;
}
if (invoice.tax_amount) {
h2 += doc.internal.getFontSize()*2;
}
//doc.rect(x1, y1, w2, h2, 'FD');
doc.setFontSize(9);
displayNotesAndTerms(doc, layout, invoice, y);
y += displaySubtotals(doc, layout, invoice, y, layout.unitCostRight);
doc.setFontSize(10);
Msg = invoice.is_quote ? invoiceLabels.total : invoiceLabels.balance_due;
var TmpMsgX = layout.unitCostRight-(doc.getStringUnitWidth(Msg) * doc.internal.getFontSize());
doc.text(TmpMsgX, y, Msg);
SetPdfColor('LightBlue', doc, 'primary');
AmountText = formatMoney(invoice.balance_amount, currencyId);
headerLeft=layout.headerRight+400;
var AmountX = layout.lineTotalRight - (doc.getStringUnitWidth(AmountText) * doc.internal.getFontSize());
doc.text(AmountX, y, AmountText);"
]);
DB::table('invoice_designs')->where('id', 2)->update([
'javascript' => " var GlobalY=0;//Y position of line at current page
var client = invoice.client;
var account = invoice.account;
var currencyId = client.currency_id;
layout.headerRight = 150;
layout.rowHeight = 15;
layout.headerTop = 125;
layout.tableTop = 300;
doc.setLineWidth(0.5);
if (NINJA.primaryColor) {
setDocHexFill(doc, NINJA.primaryColor);
setDocHexDraw(doc, NINJA.primaryColor);
} else {
doc.setFillColor(46,43,43);
}
var x1 =0;
var y1 = 0;
var w2 = 595;
var h2 = 100;
doc.rect(x1, y1, w2, h2, 'FD');
if (invoice.image)
{
var left = layout.headerRight - invoice.imageWidth;
doc.addImage(invoice.image, 'JPEG', layout.marginLeft, 30);
}
doc.setLineWidth(0.5);
if (NINJA.primaryColor) {
setDocHexFill(doc, NINJA.primaryColor);
setDocHexDraw(doc, NINJA.primaryColor);
} else {
doc.setFillColor(46,43,43);
doc.setDrawColor(46,43,43);
}
// return doc.setTextColor(240,240,240);//select color Custom Report GRAY Colour
var x1 = 0;//tableLeft-tablePadding ;
var y1 = 750;
var w2 = 596;
var h2 = 94;//doc.internal.getFontSize()*length+length*1.1;//+h;//+tablePadding;
doc.rect(x1, y1, w2, h2, 'FD');
if (!invoice.is_pro && logoImages.imageLogo2)
{
pageHeight=820;
var left = 250;//headerRight ;
y=pageHeight-logoImages.imageLogoHeight2;
var headerRight=370;
var left = headerRight - logoImages.imageLogoWidth2;
doc.addImage(logoImages.imageLogo2, 'JPEG', left, y, logoImages.imageLogoWidth2, logoImages.imageLogoHeight2);
}
doc.setFontSize(7);
doc.setFontType('bold');
SetPdfColor('White',doc);
displayAccount(doc, invoice, 300, layout.accountTop, layout);
var y = layout.accountTop;
var left = layout.marginLeft;
var headerY = layout.headerTop;
SetPdfColor('GrayLogo',doc); //set black color
doc.setFontSize(7);
//show left column
SetPdfColor('Black',doc); //set black color
doc.setFontType('normal');
//publish filled box
doc.setDrawColor(200,200,200);
if (NINJA.secondaryColor) {
setDocHexFill(doc, NINJA.secondaryColor);
} else {
doc.setFillColor(54,164,152);
}
GlobalY=190;
doc.setLineWidth(0.5);
var BlockLenght=220;
var x1 =595-BlockLenght;
var y1 = GlobalY-12;
var w2 = BlockLenght;
var h2 = getInvoiceDetailsHeight(invoice, layout) + layout.tablePadding + 2;
doc.rect(x1, y1, w2, h2, 'FD');
SetPdfColor('SomeGreen', doc, 'secondary');
doc.setFontSize('14');
doc.setFontType('bold');
doc.text(50, GlobalY, (invoice.is_quote ? invoiceLabels.your_quote : invoiceLabels.your_invoice).toUpperCase());
var z=GlobalY;
z=z+30;
doc.setFontSize('8');
SetPdfColor('Black',doc);
var clientHeight = displayClient(doc, invoice, layout.marginLeft, z, layout);
layout.tableTop += Math.max(0, clientHeight - 75);
marginLeft2=395;
//publish left side information
SetPdfColor('White',doc);
doc.setFontSize('8');
var detailsHeight = displayInvoice(doc, invoice, marginLeft2, z-25, layout) + 75;
layout.tableTop = Math.max(layout.tableTop, layout.headerTop + detailsHeight + (2 * layout.tablePadding));
y=z+60;
x = GlobalY + 100;
doc.setFontType('bold');
doc.setFontSize(12);
doc.setFontType('bold');
SetPdfColor('Black',doc);
displayInvoiceHeader(doc, invoice, layout);
var y = displayInvoiceItems(doc, invoice, layout);
doc.setLineWidth(0.3);
displayNotesAndTerms(doc, layout, invoice, y);
y += displaySubtotals(doc, layout, invoice, y, layout.unitCostRight);
doc.setFontType('bold');
doc.setFontSize(12);
x += doc.internal.getFontSize()*4;
Msg = invoice.is_quote ? invoiceLabels.total : invoiceLabels.balance_due;
var TmpMsgX = layout.unitCostRight-(doc.getStringUnitWidth(Msg) * doc.internal.getFontSize());
doc.text(TmpMsgX, y, Msg);
//SetPdfColor('LightBlue',doc);
AmountText = formatMoney(invoice.balance_amount , currencyId);
headerLeft=layout.headerRight+400;
var AmountX = headerLeft - (doc.getStringUnitWidth(AmountText) * doc.internal.getFontSize());
SetPdfColor('SomeGreen', doc, 'secondary');
doc.text(AmountX, y, AmountText);"
]);
DB::table('invoice_designs')->where('id', 3)->update([
'javascript' => " var client = invoice.client;
var account = invoice.account;
var currencyId = client.currency_id;
layout.headerRight = 400;
layout.rowHeight = 15;
doc.setFontSize(7);
// add header
doc.setLineWidth(0.5);
if (NINJA.primaryColor) {
setDocHexFill(doc, NINJA.primaryColor);
setDocHexDraw(doc, NINJA.primaryColor);
} else {
doc.setDrawColor(242,101,34);
doc.setFillColor(242,101,34);
}
var x1 =0;
var y1 = 0;
var w2 = 595;
var h2 = Math.max(110, getInvoiceDetailsHeight(invoice, layout) + 30);
doc.rect(x1, y1, w2, h2, 'FD');
SetPdfColor('White',doc);
//second column
doc.setFontType('bold');
var name = invoice.account.name;
if (name) {
doc.setFontSize('30');
doc.setFontType('bold');
doc.text(40, 50, name);
}
if (invoice.image)
{
y=130;
var left = layout.headerRight - invoice.imageWidth;
doc.addImage(invoice.image, 'JPEG', layout.marginLeft, y);
}
// add footer
doc.setLineWidth(0.5);
if (NINJA.primaryColor) {
setDocHexFill(doc, NINJA.primaryColor);
setDocHexDraw(doc, NINJA.primaryColor);
} else {
doc.setDrawColor(242,101,34);
doc.setFillColor(242,101,34);
}
var x1 = 0;//tableLeft-tablePadding ;
var y1 = 750;
var w2 = 596;
var h2 = 94;//doc.internal.getFontSize()*length+length*1.1;//+h;//+tablePadding;
doc.rect(x1, y1, w2, h2, 'FD');
if (!invoice.is_pro && logoImages.imageLogo3)
{
pageHeight=820;
// var left = 25;//250;//headerRight ;
y=pageHeight-logoImages.imageLogoHeight3;
//var headerRight=370;
//var left = headerRight - invoice.imageLogoWidth3;
doc.addImage(logoImages.imageLogo3, 'JPEG', 40, y, logoImages.imageLogoWidth3, logoImages.imageLogoHeight3);
}
doc.setFontSize(10);
var marginLeft = 340;
displayAccount(doc, invoice, marginLeft, 780, layout);
SetPdfColor('White',doc);
doc.setFontSize('8');
var detailsHeight = displayInvoice(doc, invoice, layout.headerRight, layout.accountTop-10, layout);
layout.headerTop = Math.max(layout.headerTop, detailsHeight + 50);
layout.tableTop = Math.max(layout.tableTop, detailsHeight + 150);
SetPdfColor('Black',doc); //set black color
doc.setFontSize(7);
doc.setFontType('normal');
displayClient(doc, invoice, layout.headerRight, layout.headerTop, layout);
SetPdfColor('White',doc);
doc.setFontType('bold');
doc.setLineWidth(0.3);
if (NINJA.secondaryColor) {
setDocHexFill(doc, NINJA.secondaryColor);
setDocHexDraw(doc, NINJA.secondaryColor);
} else {
doc.setDrawColor(63,60,60);
doc.setFillColor(63,60,60);
}
var left = layout.marginLeft - layout.tablePadding;
var top = layout.tableTop - layout.tablePadding;
var width = layout.marginRight - (2 * layout.tablePadding);
var height = 20;
doc.rect(left, top, width, height, 'FD');
displayInvoiceHeader(doc, invoice, layout);
SetPdfColor('Black',doc);
var y = displayInvoiceItems(doc, invoice, layout);
var height1 = displayNotesAndTerms(doc, layout, invoice, y);
var height2 = displaySubtotals(doc, layout, invoice, y, layout.unitCostRight);
y += Math.max(height1, height2);
var left = layout.marginLeft - layout.tablePadding;
var top = y - layout.tablePadding;
var width = layout.marginRight - (2 * layout.tablePadding);
var height = 20;
if (NINJA.secondaryColor) {
setDocHexFill(doc, NINJA.secondaryColor);
setDocHexDraw(doc, NINJA.secondaryColor);
} else {
doc.setDrawColor(63,60,60);
doc.setFillColor(63,60,60);
}
doc.rect(left, top, width, height, 'FD');
doc.setFontType('bold');
SetPdfColor('White', doc);
doc.setFontSize(12);
var label = invoice.is_quote ? invoiceLabels.total : invoiceLabels.balance_due;
var labelX = layout.unitCostRight-(doc.getStringUnitWidth(label) * doc.internal.getFontSize());
doc.text(labelX, y+2, label);
doc.setFontType('normal');
var amount = formatMoney(invoice.balance_amount , currencyId);
headerLeft=layout.headerRight+400;
var amountX = layout.lineTotalRight - (doc.getStringUnitWidth(amount) * doc.internal.getFontSize());
doc.text(amountX, y+2, amount);"
]);
DB::table('invoice_designs')->where('id', 4)->update([
'javascript' => " var client = invoice.client;
var account = invoice.account;
var currencyId = client.currency_id;
if (invoice.image)
{
var left = layout.headerRight - invoice.imageWidth;
doc.addImage(invoice.image, 'JPEG', left, 30);
}
/* table header */
doc.setDrawColor(200,200,200);
doc.setFillColor(230,230,230);
var detailsHeight = getInvoiceDetailsHeight(invoice, layout);
var left = layout.headerLeft - layout.tablePadding;
var top = layout.headerTop + detailsHeight - layout.rowHeight - layout.tablePadding;
var width = layout.headerRight - layout.headerLeft + (2 * layout.tablePadding);
var height = layout.rowHeight + 1;
doc.rect(left, top, width, height, 'FD');
doc.setFontSize(10);
doc.setFontType('normal');
displayAccount(doc, invoice, layout.marginLeft, layout.accountTop, layout);
displayClient(doc, invoice, layout.marginLeft, layout.headerTop, layout);
displayInvoice(doc, invoice, layout.headerLeft, layout.headerTop, layout, layout.headerRight);
layout.tableTop = Math.max(layout.tableTop, layout.headerTop + detailsHeight + (2 * layout.tablePadding));
var headerY = layout.headerTop;
var total = 0;
doc.setDrawColor(200,200,200);
doc.setFillColor(230,230,230);
var left = layout.marginLeft - layout.tablePadding;
var top = layout.tableTop - layout.tablePadding;
var width = layout.headerRight - layout.marginLeft + (2 * layout.tablePadding);
var height = layout.rowHeight + 2;
doc.rect(left, top, width, height, 'FD');
displayInvoiceHeader(doc, invoice, layout);
var y = displayInvoiceItems(doc, invoice, layout);
doc.setFontSize(10);
displayNotesAndTerms(doc, layout, invoice, y+20);
y += displaySubtotals(doc, layout, invoice, y+20, 480) + 20;
doc.setDrawColor(200,200,200);
doc.setFillColor(230,230,230);
var left = layout.footerLeft - layout.tablePadding;
var top = y - layout.tablePadding;
var width = layout.headerRight - layout.footerLeft + (2 * layout.tablePadding);
var height = layout.rowHeight + 2;
doc.rect(left, top, width, height, 'FD');
doc.setFontType('bold');
doc.text(layout.footerLeft, y, invoice.is_quote ? invoiceLabels.total : invoiceLabels.balance_due);
total = formatMoney(invoice.balance_amount, currencyId);
var totalX = layout.headerRight - (doc.getStringUnitWidth(total) * doc.internal.getFontSize());
doc.text(totalX, y, total);
if (!invoice.is_pro) {
doc.setFontType('normal');
doc.text(layout.marginLeft, 790, 'Created by InvoiceNinja.com');
}"
]);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('invoice_designs', function($table)
{
$table->dropColumn('javascript');
});
Schema::table('accounts', function($table)
{
$table->dropColumn('invoice_design');
});
}
}

View File

@ -0,0 +1,63 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddInvoiceNumberSettings extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('accounts', function($table)
{
$table->text('invoice_number_prefix')->nullable();
$table->integer('invoice_number_counter')->default(1)->nullable();
$table->text('quote_number_prefix')->nullable();
$table->integer('quote_number_counter')->default(1)->nullable();
$table->boolean('share_counter')->default(true);
});
// set initial counter value for accounts with invoices
$accounts = DB::table('accounts')->lists('id');
foreach ($accounts as $accountId) {
$invoiceNumbers = DB::table('invoices')->where('account_id', $accountId)->lists('invoice_number');
$max = 0;
foreach ($invoiceNumbers as $invoiceNumber) {
$number = intval(preg_replace('/[^0-9]/', '', $invoiceNumber));
$max = max($max, $number);
}
DB::table('accounts')->where('id', $accountId)->update(['invoice_number_counter' => ++$max]);
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('accounts', function($table)
{
$table->dropColumn('invoice_number_prefix');
$table->dropColumn('invoice_number_counter');
$table->dropColumn('quote_number_prefix');
$table->dropColumn('quote_number_counter');
$table->dropColumn('share_counter');
});
}
}

View File

@ -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(

View File

@ -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');

View File

@ -422,5 +422,17 @@ 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',
'invoice_settings' => 'Invoice Settings',
'invoice_number_prefix' => 'Invoice Number Prefix',
'invoice_number_counter' => 'Invoice Number Counter',
'quote_number_prefix' => 'Quote Number Prefix',
'quote_number_counter' => 'Quote Number Counter',
'share_invoice_counter' => 'Share invoice counter',
'invoice_issued_to' => 'Invoice issued to',
'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix',
'mark_sent' => 'Mark sent',
);

View File

@ -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.',
@ -430,6 +430,19 @@ 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',
'invoice_settings' => 'Invoice Settings',
'invoice_number_prefix' => 'Invoice Number Prefix',
'invoice_number_counter' => 'Invoice Number Counter',
'quote_number_prefix' => 'Quote Number Prefix',
'quote_number_counter' => 'Quote Number Counter',
'share_invoice_counter' => 'Share invoice counter',
'invoice_issued_to' => 'Invoice issued to',
'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix',
'mark_sent' => 'Mark sent',
);

View File

@ -420,5 +420,18 @@ 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',
'invoice_settings' => 'Invoice Settings',
'invoice_number_prefix' => 'Invoice Number Prefix',
'invoice_number_counter' => 'Invoice Number Counter',
'quote_number_prefix' => 'Quote Number Prefix',
'quote_number_counter' => 'Quote Number Counter',
'share_invoice_counter' => 'Share invoice counter',
'invoice_issued_to' => 'Invoice issued to',
'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix',
'mark_sent' => 'Mark sent',
);

View File

@ -422,6 +422,19 @@ 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',
'invoice_settings' => 'Invoice Settings',
'invoice_number_prefix' => 'Invoice Number Prefix',
'invoice_number_counter' => 'Invoice Number Counter',
'quote_number_prefix' => 'Quote Number Prefix',
'quote_number_counter' => 'Quote Number Counter',
'share_invoice_counter' => 'Share invoice counter',
'invoice_issued_to' => 'Invoice issued to',
'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix',
'mark_sent' => 'Mark sent',
);

View File

@ -422,5 +422,19 @@ 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',
'invoice_settings' => 'Invoice Settings',
'invoice_number_prefix' => 'Invoice Number Prefix',
'invoice_number_counter' => 'Invoice Number Counter',
'quote_number_prefix' => 'Quote Number Prefix',
'quote_number_counter' => 'Quote Number Counter',
'share_invoice_counter' => 'Share invoice counter',
'invoice_issued_to' => 'Invoice issued to',
'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix',
'mark_sent' => 'Mark sent',
);

View File

@ -430,6 +430,19 @@ 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',
'invoice_settings' => 'Invoice Settings',
'invoice_number_prefix' => 'Invoice Number Prefix',
'invoice_number_counter' => 'Invoice Number Counter',
'quote_number_prefix' => 'Quote Number Prefix',
'quote_number_counter' => 'Quote Number Counter',
'share_invoice_counter' => 'Share invoice counter',
'invoice_issued_to' => 'Invoice issued to',
'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix',
'mark_sent' => 'Mark sent',
);

View File

@ -430,6 +430,19 @@ 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',
'invoice_settings' => 'Invoice Settings',
'invoice_number_prefix' => 'Invoice Number Prefix',
'invoice_number_counter' => 'Invoice Number Counter',
'quote_number_prefix' => 'Quote Number Prefix',
'quote_number_counter' => 'Quote Number Counter',
'share_invoice_counter' => 'Share invoice counter',
'invoice_issued_to' => 'Invoice issued to',
'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix',
'mark_sent' => 'Mark sent',
);

View File

@ -423,6 +423,19 @@ 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',
'invoice_settings' => 'Invoice Settings',
'invoice_number_prefix' => 'Invoice Number Prefix',
'invoice_number_counter' => 'Invoice Number Counter',
'quote_number_prefix' => 'Quote Number Prefix',
'quote_number_counter' => 'Quote Number Counter',
'share_invoice_counter' => 'Share invoice counter',
'invoice_issued_to' => 'Invoice issued to',
'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix',
'mark_sent' => 'Mark sent',
);

View File

@ -411,6 +411,19 @@ 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',
'invoice_settings' => 'Invoice Settings',
'invoice_number_prefix' => 'Invoice Number Prefix',
'invoice_number_counter' => 'Invoice Number Counter',
'quote_number_prefix' => 'Quote Number Prefix',
'quote_number_counter' => 'Quote Number Counter',
'share_invoice_counter' => 'Share invoice counter',
'invoice_issued_to' => 'Invoice issued to',
'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix',
'mark_sent' => 'Mark sent',
);

View File

@ -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;
}
}

View File

@ -141,26 +141,23 @@ class Account extends Eloquent
return $height;
}
public function getNextInvoiceNumber()
public function getNextInvoiceNumber($isQuote = false)
{
$invoices = Invoice::withTrashed()->scope(false, $this->id)->get(['invoice_number']);
$counter = $isQuote && !$this->share_counter ? $this->quote_number_counter : $this->invoice_number_counter;
$prefix = $isQuote ? $this->quote_number_prefix : $this->invoice_number_prefix;
$max = 0;
return $prefix . str_pad($counter, 4, "0", STR_PAD_LEFT);
}
foreach ($invoices as $invoice)
{
$number = intval(preg_replace("/[^0-9]/", "", $invoice->invoice_number));
$max = max($max, $number);
public function incrementCounter($isQuote = false)
{
if ($isQuote && !$this->share_counter) {
$this->quote_number_counter += 1;
} else {
$this->invoice_number_counter += 1;
}
if ($max > 0)
{
return str_pad($max+1, 4, "0", STR_PAD_LEFT);
}
else
{
return DEFAULT_INVOICE_NUMBER;
}
$this->save();
}
public function getLocale()
@ -208,6 +205,7 @@ class Account extends Eloquent
'quote_date',
'quote_number',
'total',
'invoice_issued_to',
];
foreach ($fields as $field)
@ -290,7 +288,11 @@ class Account extends Eloquent
foreach ($client->contacts as $contact)
{
$contact->setVisible(['public_id']);
$contact->setVisible([
'public_id',
'first_name',
'last_name',
'email']);
}
}

View File

@ -27,6 +27,11 @@ class Invoice extends EntityModel
return $this->belongsTo('InvoiceStatus');
}
public function invoice_design()
{
return $this->belongsTo('InvoiceDesign');
}
public function invitations()
{
return $this->hasMany('Invitation');
@ -79,6 +84,7 @@ class Invoice extends EntityModel
'tax_name',
'tax_rate',
'account',
'invoice_design',
'invoice_design_id',
'is_pro',
'is_quote',
@ -211,6 +217,7 @@ class Invoice extends EntityModel
Invoice::created(function($invoice)
{
$invoice->account->incrementCounter($invoice->is_quote);
Activity::createInvoice($invoice);
});

View File

@ -20,7 +20,7 @@ class InvoiceRepository
->where('contacts.deleted_at', '=', null)
->where('invoices.is_recurring', '=', false)
->where('contacts.is_primary', '=', true)
->select('clients.public_id as client_public_id', 'invoice_number', 'clients.name as client_name', 'invoices.public_id', 'amount', 'invoices.balance', 'invoice_date', 'due_date', 'invoice_statuses.name as invoice_status_name', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'quote_id', 'quote_invoice_id');
->select('clients.public_id as client_public_id', 'invoice_number', 'invoice_status_id', 'clients.name as client_name', 'invoices.public_id', 'amount', 'invoices.balance', 'invoice_date', 'due_date', 'invoice_statuses.name as invoice_status_name', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'quote_id', 'quote_invoice_id');
if (!\Session::get('show_trash:invoice'))
{
@ -121,32 +121,40 @@ class InvoiceRepository
<ul class="dropdown-menu" role="menu">
<li><a href="' . \URL::to("{$entityType}s/".$model->public_id.'/edit') . '">'.trans("texts.edit_{$entityType}").'</a></li>
<li><a href="' . \URL::to("{$entityType}s/".$model->public_id.'/clone') . '">'.trans("texts.clone_{$entityType}").'</a></li>
<li class="divider"></li><li>';
<li class="divider"></li>';
if ($entityType == ENTITY_INVOICE)
{
$str .= '<a href="' . \URL::to('payments/create/' . $model->client_public_id . '/' . $model->public_id ) . '">'.trans('texts.enter_payment').'</a></li>';
if ($model->quote_id)
if ($model->invoice_status_id < INVOICE_STATUS_SENT)
{
$str .= '<li><a href="' . \URL::to("quotes/{$model->quote_id}/edit") . '">' . trans("texts.view_quote") . '</a></li>';
$str .= '<li><a href="javascript:markEntity(' . $model->public_id . ', ' . INVOICE_STATUS_SENT . ')">'.trans("texts.mark_sent").'</a></li>';
}
}
else if ($entityType == ENTITY_QUOTE)
{
if ($model->quote_invoice_id)
{
$str .= '<li><a href="' . \URL::to("invoices/{$model->quote_invoice_id}/edit") . '">' . trans("texts.view_invoice") . '</a></li>';
}
}
return $str . '<li class="divider"></li>
<li><a href="javascript:archiveEntity(' . $model->public_id . ')">'.trans("texts.archive_{$entityType}").'</a></li>
<li><a href="javascript:deleteEntity(' . $model->public_id . ')">'.trans("texts.delete_{$entityType}").'</a></li>
</ul>
</div>';
})
->make();
if ($entityType == ENTITY_INVOICE)
{
if ($model->invoice_status_id < INVOICE_STATUS_PAID)
{
$str .= '<li><a href="' . \URL::to('payments/create/' . $model->client_public_id . '/' . $model->public_id ) . '">'.trans('texts.enter_payment').'</a></li>';
}
if ($model->quote_id)
{
$str .= '<li><a href="' . \URL::to("quotes/{$model->quote_id}/edit") . '">' . trans("texts.view_quote") . '</a></li>';
}
}
else if ($entityType == ENTITY_QUOTE)
{
if ($model->quote_invoice_id)
{
$str .= '<li><a href="' . \URL::to("invoices/{$model->quote_invoice_id}/edit") . '">' . trans("texts.view_invoice") . '</a></li>';
}
}
return $str . '<li class="divider"></li>
<li><a href="javascript:archiveEntity(' . $model->public_id . ')">'.trans("texts.archive_{$entityType}").'</a></li>
<li><a href="javascript:deleteEntity(' . $model->public_id . ')">'.trans("texts.delete_{$entityType}").'</a></li>
</ul>
</div>';
})
->make();
}
@ -359,12 +367,11 @@ class InvoiceRepository
$clone = Invoice::createNew($invoice);
$clone->balance = $invoice->amount;
$clone->invoice_number = $invoice->account->getNextInvoiceNumber();
$clone->invoice_number = $invoice->account->getNextInvoiceNumber($invoice->is_quote);
foreach ([
'client_id',
'discount',
//'shipping',
'invoice_date',
'po_number',
'due_date',
@ -378,7 +385,11 @@ class InvoiceRepository
'tax_name',
'tax_rate',
'amount',
'is_quote'] as $field)
'is_quote',
'custom_value1',
'custom_value2',
'custom_taxes1',
'custom_taxes2'] as $field)
{
$clone->$field = $invoice->$field;
}
@ -428,7 +439,7 @@ class InvoiceRepository
}
public function bulk($ids, $action)
public function bulk($ids, $action, $statusId = false)
{
if (!$ids)
{
@ -439,13 +450,21 @@ class InvoiceRepository
foreach ($invoices as $invoice)
{
if ($action == 'delete')
{
$invoice->is_deleted = true;
$invoice->save();
}
if ($action == 'mark')
{
$invoice->invoice_status_id = $statusId;
$invoice->save();
}
else
{
if ($action == 'delete')
{
$invoice->is_deleted = true;
$invoice->save();
}
$invoice->delete();
$invoice->delete();
}
}
return count($invoices);

View File

@ -1,5 +1,6 @@
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
@ -36,7 +37,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 +55,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 +65,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'));
@ -167,7 +171,7 @@ define('ACCOUNT_MAP', 'import_map');
define('ACCOUNT_EXPORT', 'export');
define('ACCOUNT_PRODUCTS', 'products');
define('ACCOUNT_ADVANCED_SETTINGS', 'advanced_settings');
define('ACCOUNT_CUSTOM_FIELDS', 'custom_fields');
define('ACCOUNT_INVOICE_SETTINGS', 'invoice_settings');
define('ACCOUNT_INVOICE_DESIGN', 'invoice_design');
define('ACCOUNT_CHART_BUILDER', 'chart_builder');
define('ACCOUNT_USER_MANAGEMENT', 'user_management');
@ -236,11 +240,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);

View File

@ -1,49 +1,103 @@
@extends('accounts.nav')
@section('head')
@parent
<script src="{{ asset('js/pdf_viewer.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/compatibility.js') }}" type="text/javascript"></script>
@stop
@section('content')
@parent
@include('accounts.nav_advanced')
{{ Former::open()->addClass('col-md-8 col-md-offset-2 warn-on-exit') }}
{{ Former::populate($account) }}
{{ Former::populateField('hide_quantity', intval($account->hide_quantity)) }}
{{ Former::populateField('hide_paid_to_date', intval($account->hide_paid_to_date)) }}
<script>
var invoiceDesigns = {{ $invoiceDesigns }};
var invoice = {{ json_encode($invoice) }};
{{ Former::legend('invoice_options') }}
{{ Former::checkbox('hide_quantity')->text(trans('texts.hide_quantity_help')) }}
{{ Former::checkbox('hide_paid_to_date')->text(trans('texts.hide_paid_to_date_help')) }}
<p>&nbsp;</p>
function getDesignJavascript() {
var id = $('#invoice_design_id').val();
return invoiceDesigns[id-1].javascript;
}
{{ Former::legend('invoice_design') }}
{{ Former::text('primary_color') }}
{{ Former::text('secondary_color') }}
function getPDFString() {
invoice.is_pro = {{ Auth::user()->isPro() ? 'true' : 'false' }};
invoice.account.hide_quantity = $('#hide_quantity').is(":checked");
invoice.account.hide_paid_to_date = $('#hide_paid_to_date').is(":checked");
invoice.invoice_design_id = $('#invoice_design_id').val();
@if (Auth::user()->isPro())
{{ Former::actions( Button::lg_success_submit(trans('texts.save'))->append_with_icon('floppy-disk') ) }}
@else
<script>
$(function() {
$('form.warn-on-exit input').prop('disabled', true);
});
</script>
@endif
NINJA.primaryColor = $('#primary_color').val();
NINJA.secondaryColor = $('#secondary_color').val();
{{ Former::close() }}
var doc = generatePDF(invoice, getDesignJavascript(), true);
if (!doc) {
return;
}
return doc.output('datauristring');
}
<script>
$(function() {
var options = {
preferredFormat: "hex",
disabled: {{ Auth::user()->isPro() ? 'false' : 'true' }},
showInitial: false,
showInput: true,
allowEmpty: true,
clickoutFiresChange: true,
};
$('#primary_color').spectrum(options);
$('#secondary_color').spectrum(options);
});
</script>
$(function() {
var options = {
preferredFormat: 'hex',
disabled: {{ Auth::user()->isPro() ? 'false' : 'true' }},
showInitial: false,
showInput: true,
allowEmpty: true,
clickoutFiresChange: true,
};
$('#primary_color').spectrum(options);
$('#secondary_color').spectrum(options);
refreshPDF();
});
</script>
<div class="row">
<div class="col-md-6">
{{ Former::open()->addClass('warn-on-exit')->onchange('refreshPDF()') }}
{{ Former::populate($account) }}
{{ Former::populateField('hide_quantity', intval($account->hide_quantity)) }}
{{ Former::populateField('hide_paid_to_date', intval($account->hide_paid_to_date)) }}
{{ Former::legend('invoice_design') }}
{{ Former::select('invoice_design_id')->style('display:inline;width:120px')
->fromQuery($invoiceDesigns, 'name', 'id') }}
{{ Former::text('primary_color') }}
{{ Former::text('secondary_color') }}
<p>&nbsp;</p>
<p>&nbsp;</p>
{{ Former::legend('invoice_options') }}
{{ Former::checkbox('hide_quantity')->text(trans('texts.hide_quantity_help')) }}
{{ Former::checkbox('hide_paid_to_date')->text(trans('texts.hide_paid_to_date_help')) }}
<p>&nbsp;</p>
<p>&nbsp;</p>
@if (Auth::user()->isPro())
{{ Former::actions( Button::lg_success_submit(trans('texts.save'))->append_with_icon('floppy-disk') ) }}
@else
<script>
$(function() {
$('form.warn-on-exit input').prop('disabled', true);
});
</script>
@endif
{{ Former::close() }}
</div>
<div class="col-md-6">
@include('invoices.pdf', ['account' => Auth::user()->account, 'pdfHeight' => 800])
</div>
</div>
@stop

View File

@ -8,6 +8,8 @@
{{ Former::populate($account) }}
{{ Former::populateField('custom_invoice_taxes1', intval($account->custom_invoice_taxes1)) }}
{{ Former::populateField('custom_invoice_taxes2', intval($account->custom_invoice_taxes2)) }}
{{ Former::populateField('share_counter', intval($account->share_counter)) }}
{{ Former::legend('invoice_fields') }}
{{ Former::text('custom_invoice_label1')->label(trans('texts.field_label'))
@ -27,17 +29,45 @@
<p>&nbsp;</p>
{{ Former::text('custom_label2')->label(trans('texts.field_label')) }}
{{ Former::text('custom_value2')->label(trans('texts.field_value')) }}
<p>&nbsp;</p>
{{ Former::legend('invoice_number') }}
{{ Former::text('invoice_number_prefix')->label(trans('texts.invoice_number_prefix')) }}
{{ Former::text('invoice_number_counter')->label(trans('texts.invoice_number_counter')) }}
<p>&nbsp;</p>
{{ Former::legend('quote_number') }}
{{ Former::text('quote_number_prefix')->label(trans('texts.quote_number_prefix')) }}
{{ Former::text('quote_number_counter')->label(trans('texts.quote_number_counter'))
->append(Former::checkbox('share_counter')->raw()->onclick('setQuoteNumberEnabled()') . ' ' . trans('texts.share_invoice_counter')) }}
<p>&nbsp;</p>
@if (Auth::user()->isPro())
{{ Former::actions( Button::lg_success_submit(trans('texts.save'))->append_with_icon('floppy-disk') ) }}
@else
<script>
$(function() {
$('form.warn-on-exit input').prop('disabled', true);
});
$(function() {
$('form.warn-on-exit input').prop('disabled', true);
});
</script>
@endif
{{ Former::close() }}
<script type="text/javascript">
function setQuoteNumberEnabled() {
var disabled = $('#share_counter').prop('checked');
$('#quote_number_counter').prop('disabled', disabled);
$('#quote_number_counter').val(disabled ? '' : '{{ $account->quote_number_counter }}');
}
$(function() {
setQuoteNumberEnabled();
});
</script>
@stop

View File

@ -8,7 +8,7 @@
{{ HTML::nav_link('company/products', 'product_library') }}
{{ HTML::nav_link('company/notifications', 'notifications') }}
{{ HTML::nav_link('company/import_export', 'import_export', 'company/import_map') }}
{{ HTML::nav_link('company/advanced_settings/custom_fields', 'advanced_settings', '*/advanced_settings/*') }}
{{ HTML::nav_link('company/advanced_settings/invoice_settings', 'advanced_settings', '*/advanced_settings/*') }}
</ul>
<br/>

View File

@ -1,5 +1,5 @@
<ul class="nav nav-tabs nav nav-justified">
{{ HTML::nav_link('company/advanced_settings/custom_fields', 'custom_fields') }}
{{ HTML::nav_link('company/advanced_settings/invoice_settings', 'invoice_settings') }}
{{ HTML::nav_link('company/advanced_settings/invoice_design', 'invoice_design') }}
{{ HTML::nav_link('company/advanced_settings/data_visualizations', 'data_visualizations') }}
{{ HTML::nav_link('company/advanced_settings/chart_builder', 'chart_builder') }}

View File

@ -4,6 +4,15 @@
@parent
@include('accounts.nav_advanced')
{{ Former::open('users/delete')->addClass('user-form') }}
{{ Former::legend('user_management') }}
<div style="display:none">
{{ Former::text('userPublicId') }}
</div>
{{ Former::close() }}
@if (Utils::isPro())
{{ Button::success_link(URL::to('users/create'), trans("texts.add_user"), array('class' => 'pull-right'))->append_with_icon('plus-sign') }}
@endif
@ -22,13 +31,6 @@
->setOptions('aoColumnDefs', [['bSortable'=>false, 'aTargets'=>[3]]])
->render('datatable') }}
{{ Former::open('users/delete')->addClass('user-form') }}
<div style="display:none">
{{ Former::text('userPublicId') }}
</div>
{{ Former::close() }}
<script>
window.onDatatableReady = function() {
$('tbody tr').mouseover(function() {

View File

@ -2,46 +2,21 @@
@section('head')
<meta name="csrf-token" content="<?= csrf_token() ?>">
<link href="{{ asset('built.css') }}" rel="stylesheet" type="text/css"/>
<!--
<script src="{{ asset('vendor/jquery/dist/jquery.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/jquery-ui/ui/minified/jquery-ui.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/bootstrap/dist/js/bootstrap.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/datatables/media/js/jquery.dataTables.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/datatables-bootstrap3/BS3/assets/js/datatables.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/knockout.js/knockout.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/knockout-mapping/build/output/knockout.mapping-latest.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/knockout-sortable/build/knockout-sortable.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/underscore/underscore.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/bootstrap-datepicker/js/bootstrap-datepicker.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/typeahead.js/dist/typeahead.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/accounting/accounting.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('vendor/spectrum/spectrum.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/bootstrap-combobox.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/jspdf.source.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/jspdf.plugin.split_text_to_size.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/script.js') }}" type="text/javascript"></script>
-->
<!--
<link href="{{ asset('vendor/bootstrap/dist/css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('vendor/datatables/media/css/jquery.dataTables.css') }}" rel="stylesheet" type="text/css">
<link href="{{ asset('vendor/datatables-bootstrap3/BS3/assets/css/datatables.css') }}" rel="stylesheet" type="text/css">
<link href="{{ asset('vendor/font-awesome/css/font-awesome.min.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('vendor/bootstrap-datepicker/css/datepicker.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('vendor/spectrum/spectrum.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/bootstrap-combobox.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/typeahead.js-bootstrap.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/style.css') }}" rel="stylesheet" type="text/css"/>
-->
<link href="{{ asset('built.css') }}?no_cache={{ NINJA_VERSION }}" rel="stylesheet" type="text/css"/>
<style type="text/css">
body {
/* background-color: #F6F6F6; */
background-color: #EEEEEE;
padding-top: 114px;
}
/* Fix for header covering stuff when the screen is narrower */
@media screen and (min-width: 1200px) {
body {
padding-top: 50px;
}
}
</style>
@ -67,8 +42,6 @@
@section('body')
<p>&nbsp;</p>
<p>&nbsp;</p>
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
@ -136,7 +109,7 @@
<li>{{ link_to('company/products', uctrans('texts.product_library')) }}</li>
<li>{{ link_to('company/notifications', uctrans('texts.notifications')) }}</li>
<li>{{ link_to('company/import_export', uctrans('texts.import_export')) }}</li>
<li><a href="{{ url('company/advanced_settings/custom_fields') }}">{{ uctrans('texts.advanced_settings') . Utils::getProLabel(ACCOUNT_ADVANCED_SETTINGS) }}</a></li>
<li><a href="{{ url('company/advanced_settings/invoice_settings') }}">{{ uctrans('texts.advanced_settings') . Utils::getProLabel(ACCOUNT_ADVANCED_SETTINGS) }}</a></li>
<li class="divider"></li>
<li>{{ link_to('#', trans('texts.logout'), array('onclick'=>'logout()')) }}</li>
@ -197,7 +170,14 @@
@endif
@if (Session::has('message'))
<div class="alert alert-info">{{ Session::get('message') }}</div>
<div class="alert alert-info">
{{ Session::get('message') }}
</div>
@elseif (Session::has('news_feed_message'))
<div class="alert alert-info">
{{ Session::get('news_feed_message') }}
<a href="#" onclick="hideMessage()" class="pull-right">{{ trans('texts.hide') }}</a>
</div>
@endif
@if (Session::has('error'))
@ -542,6 +522,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(){

View File

@ -318,10 +318,7 @@
</div>
<p>&nbsp;</p>
<!-- <textarea rows="20" cols="120" id="pdfText" onkeyup="runCode()"></textarea> -->
<!-- <iframe frameborder="1" width="100%" height="600" style="display:block;margin: 0 auto"></iframe> -->
<iframe id="theFrame" style="display:none" frameborder="1" width="100%" height="1180"></iframe>
<canvas id="theCanvas" style="display:none;width:100%;border:solid 1px #CCCCCC;"></canvas>
@include('invoices.pdf', ['account' => Auth::user()->account])
@if (!Auth::user()->account->isPro())
<div style="font-size:larger">
@ -643,76 +640,20 @@
invoice.imageHeight = {{ $account->getLogoHeight() }};
@endif
window.logoImages = {};
logoImages.imageLogo1 = "{{ HTML::image_data('images/report_logo1.jpg') }}";
logoImages.imageLogoWidth1 =120;
logoImages.imageLogoHeight1 = 40
logoImages.imageLogo2 = "{{ HTML::image_data('images/report_logo2.jpg') }}";
logoImages.imageLogoWidth2 =325/2;
logoImages.imageLogoHeight2 = 81/2;
logoImages.imageLogo3 = "{{ HTML::image_data('images/report_logo3.jpg') }}";
logoImages.imageLogoWidth3 =325/2;
logoImages.imageLogoHeight3 = 81/2;
return invoice;
}
/*
function refreshPDF() {
setTimeout(function() {
_refreshPDF();
}, 100);
}
*/
var isRefreshing = false;
var needsRefresh = false;
function getPDFString() {
var invoice = createInvoiceModel();
var doc = generatePDF(invoice);
var design = getDesignJavascript();
var doc = generatePDF(invoice, design);
if (!doc) return;
return doc.output('datauristring');
}
function refreshPDF() {
if ({{ Auth::user()->force_pdfjs ? 'false' : 'true' }} && (isFirefox || (isChrome && !isChromium))) {
var string = getPDFString();
if (!string) return;
$('#theFrame').attr('src', string).show();
} else {
if (isRefreshing) {
needsRefresh = true;
return;
}
var string = getPDFString();
if (!string) return;
isRefreshing = true;
var pdfAsArray = convertDataURIToBinary(string);
PDFJS.getDocument(pdfAsArray).then(function getPdfHelloWorld(pdf) {
pdf.getPage(1).then(function getPageHelloWorld(page) {
var scale = 1.5;
var viewport = page.getViewport(scale);
var canvas = document.getElementById('theCanvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({canvasContext: context, viewport: viewport});
$('#theCanvas').show();
isRefreshing = false;
if (needsRefresh) {
needsRefresh = false;
refreshPDF();
}
});
});
}
function getDesignJavascript() {
var id = $('#invoice_design_id').val();
return invoiceDesigns[id-1].javascript;
}
function onDownloadClick() {
@ -1561,9 +1502,10 @@
var products = {{ $products }};
var clients = {{ $clients }};
var invoiceLabels = {{ json_encode($invoiceLabels) }};
var clientMap = {};
var $clientSelect = $('select#client');
var invoiceDesigns = {{ $invoiceDesigns }};
for (var i=0; i<clients.length; i++) {
var client = clients[i];

View File

@ -0,0 +1,71 @@
<iframe id="theFrame" style="display:none" frameborder="1" width="100%" height="{{ isset($pdfHeight) ? $pdfHeight : 1180 }}px"></iframe>
<canvas id="theCanvas" style="display:none;width:100%;border:solid 1px #CCCCCC;"></canvas>
<script type="text/javascript">
window.logoImages = {};
logoImages.imageLogo1 = "{{ HTML::image_data('images/report_logo1.jpg') }}";
logoImages.imageLogoWidth1 =120;
logoImages.imageLogoHeight1 = 40
logoImages.imageLogo2 = "{{ HTML::image_data('images/report_logo2.jpg') }}";
logoImages.imageLogoWidth2 =325/2;
logoImages.imageLogoHeight2 = 81/2;
logoImages.imageLogo3 = "{{ HTML::image_data('images/report_logo3.jpg') }}";
logoImages.imageLogoWidth3 =325/2;
logoImages.imageLogoHeight3 = 81/2;
@if (file_exists($account->getLogoPath()))
invoice.image = "{{ HTML::image_data($account->getLogoPath()) }}";
invoice.imageWidth = {{ $account->getLogoWidth() }};
invoice.imageHeight = {{ $account->getLogoHeight() }};
@endif
var NINJA = NINJA || {};
NINJA.primaryColor = "{{ $account->primary_color }}";
NINJA.secondaryColor = "{{ $account->secondary_color }}";
var invoiceLabels = {{ json_encode($account->getInvoiceLabels()) }};
var isRefreshing = false;
var needsRefresh = false;
function refreshPDF() {
if ({{ Auth::check() && Auth::user()->force_pdfjs ? 'false' : 'true' }} && (isFirefox || (isChrome && !isChromium))) {
var string = getPDFString();
if (!string) return;
$('#theFrame').attr('src', string).show();
} else {
if (isRefreshing) {
needsRefresh = true;
return;
}
var string = getPDFString();
if (!string) return;
isRefreshing = true;
var pdfAsArray = convertDataURIToBinary(string);
PDFJS.getDocument(pdfAsArray).then(function getPdfHelloWorld(pdf) {
pdf.getPage(1).then(function getPageHelloWorld(page) {
var scale = 1.5;
var viewport = page.getViewport(scale);
var canvas = document.getElementById('theCanvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({canvasContext: context, viewport: viewport});
$('#theCanvas').show();
isRefreshing = false;
if (needsRefresh) {
needsRefresh = false;
refreshPDF();
}
});
});
}
}
</script>

View File

@ -36,8 +36,7 @@
<div class="clearfix"></div><p>&nbsp;</p>
<iframe id="theFrame" frameborder="1" width="100%" height="1180" style="display:none;margin: 0 auto"></iframe>
<canvas id="theCanvas" style="display:none;width:100%;border:solid 1px #CCCCCC;"></canvas>
@include('invoices.pdf', ['account' => $invoice->client->account])
<p>&nbsp;</p>
<p>&nbsp;</p>
@ -46,62 +45,20 @@
<script type="text/javascript">
$(function() {
window.invoice = {{ $invoice->toJson() }};
window.logoImages = {};
window.invoice = {{ $invoice->toJson() }};
invoice.is_pro = {{ $invoice->client->account->isPro() ? 'true' : 'false' }};
invoice.is_quote = {{ $invoice->is_quote ? 'true' : 'false' }};
logoImages.imageLogo1 = "{{ HTML::image_data('images/report_logo1.jpg') }}";
logoImages.imageLogoWidth1 =120;
logoImages.imageLogoHeight1 = 40
logoImages.imageLogo2 = "{{ HTML::image_data('images/report_logo2.jpg') }}";
logoImages.imageLogoWidth2 =325/2;
logoImages.imageLogoHeight2 = 81/2;
logoImages.imageLogo3 = "{{ HTML::image_data('images/report_logo3.jpg') }}";
logoImages.imageLogoWidth3 =325/2;
logoImages.imageLogoHeight3 = 81/2;
@if (file_exists($invoice->client->account->getLogoPath()))
invoice.image = "{{ HTML::image_data($invoice->client->account->getLogoPath()) }}";
invoice.imageWidth = {{ $invoice->client->account->getLogoWidth() }};
invoice.imageHeight = {{ $invoice->client->account->getLogoHeight() }};
@endif
invoice.is_quote = {{ $invoice->is_quote ? 'true' : 'false' }};
var NINJA = NINJA || {};
NINJA.primaryColor = "{{ $invoice->client->account->primary_color }}";
NINJA.secondaryColor = "{{ $invoice->client->account->secondary_color }}";
var doc = generatePDF(invoice);
function getPDFString() {
var doc = generatePDF(invoice, invoice.invoice_design.javascript);
if (!doc) return;
var string = doc.output('datauristring');
return doc.output('datauristring');
}
if (isFirefox || (isChrome && !isChromium)) {
$('#theFrame').attr('src', string).show();
} else {
var pdfAsArray = convertDataURIToBinary(string);
PDFJS.getDocument(pdfAsArray).then(function getPdfHelloWorld(pdf) {
pdf.getPage(1).then(function getPageHelloWorld(page) {
var scale = 1.5;
var viewport = page.getViewport(scale);
var canvas = document.getElementById('theCanvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({canvasContext: context, viewport: viewport});
$('#theCanvas').show();
});
});
}
$(function() {
refreshPDF();
});
var invoiceLabels = {{ json_encode($invoiceLabels) }};
function onDownloadClick() {
var doc = generatePDF(invoice, true);
doc.save('Invoice-' + invoice.invoice_number + '.pdf');

View File

@ -5,6 +5,7 @@
{{ Former::open($entityType . 's/bulk')->addClass('listForm') }}
<div style="display:none">
{{ Former::text('action') }}
{{ Former::text('statusId') }}
{{ Former::text('id') }}
</div>
@ -67,6 +68,12 @@
submitForm('archive');
}
function markEntity(id, statusId) {
$('#id').val(id);
$('#statusId').val(statusId);
submitForm('mark');
}
function setTrashVisible() {
var checked = $('#trashed').is(':checked');
window.location = '{{ URL::to('view_archive/' . $entityType) }}' + (checked ? '/true' : '/false');

View File

@ -15,13 +15,18 @@
<meta property="og:description" content="Simple, Intuitive Invoicing."></meta>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="<?= csrf_token() ?>">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href='//fonts.googleapis.com/css?family=Roboto:400,700,900,100' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Roboto+Slab:400,300,700' rel='stylesheet' type='text/css'>
<link href="{{ asset('favicon.ico') }}" rel="icon" type="image/x-icon">
<script src="{{ asset('built.js') }}" type="text/javascript"></script>
@if (!Utils::isNinja())
<link rel="canonical" href="https://www.invoiceninja.com"></link>
@endif
<script src="{{ asset('built.js') }}?no_cache={{ NINJA_VERSION }}" type="text/javascript"></script>
<script type="text/javascript">
var NINJA = NINJA || {};
@ -90,7 +95,6 @@
</script>
@endif
@yield('body')
<script type="text/javascript">

View File

@ -1,24 +1,9 @@
@extends('master')
@section('head')
<meta name="csrf-token" content="<?= csrf_token() ?>">
<link href="{{ asset('built.public.css') }}" rel="stylesheet" type="text/css"/>
<!--
<link href="{{ asset('vendor/bootstrap/dist/css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/bootstrap.splash.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/splash.css') }}" rel="stylesheet" type="text/css"/>
-->
<!--
<link href="{{ asset('images/apple-touch-icon-114x114-precomposed.png') }}" rel="apple-touch-icon-precomposed" sizes="114x114">
<link href="{{ asset('images/apple-touch-icon-72x72-precomposed.png') }}" rel="apple-touch-icon-precomposed" sizes="72x72">
<link href="{{ asset('images/apple-touch-icon-57x57-precomposed.png') }}" rel="apple-touch-icon-precomposed">
-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="{{ asset('js/simpleexpand.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/valign.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/bootstrap.min.js') }}" type="text/javascript"></script>
<link href="{{ asset('built.public.css') }}?no_cache={{ NINJA_VERSION }}" rel="stylesheet" type="text/css"/>
<script src="{{ asset('js/built.public.js') }}?no_cache={{ NINJA_VERSION }}" type="text/javascript"></script>
<style>
.hero {

View File

@ -3,7 +3,7 @@
@section('head')
@parent
<script src="{{ asset('vendor/d3/d3.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/d3.min.js') }}" type="text/javascript"></script>
<style type="text/css">
@ -53,7 +53,7 @@
<option>Invoices</option>
<option>Products</option>
</select>
&nbsp;&nbsp; {{ $message }}
&nbsp;&nbsp; <b>{{ $message }}</b>
</form>
<p>&nbsp;</p>
@ -93,7 +93,7 @@
paid: d3.sum(d, function(g) {
return g.invoice && g.invoice.invoice_status_id == 5 ? (g.qty * g.cost) : 0;
}),
age: d3.median(d, function(g) {
age: d3.mean(d, function(g) {
return calculateInvoiceAge(g.invoice) || null;
}),
}})
@ -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) {
@ -168,8 +168,8 @@
.padding(12);
var svg = d3.select(".svg-div").append("svg")
.attr("width", "100%")
.attr("height", "100%")
.attr("width", "1142px")
.attr("height", "1142px")
.attr("class", "bubble");
svg.append("rect")
@ -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));

View File

@ -16,7 +16,6 @@
"bootstrap-datepicker": "~1.*",
"typeahead.js": "~0.9.3",
"accounting": "~0.*",
"pdfjs": "*",
"spectrum": "~1.3.4",
"handsontable": "*",
"d3": "~3.4.11"

734
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "65f2ef5897c7ec4d7396b49a429fb1c6",
"hash": "0a1d0827dad7ba209f75b0869a8e42ec",
"packages": [
{
"name": "anahkiasen/former",
@ -97,7 +97,7 @@
],
"authors": [
{
"name": "Anahkiasen",
"name": "Maxime Fabre",
"email": "ehtnam6@gmail.com"
}
],
@ -156,12 +156,12 @@
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "1a37b2f1dd66d36c5b8f19f4ab2f38cfc794a238"
"reference": "6da284de7eeb57b7c120513998b712a718a3504a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/1a37b2f1dd66d36c5b8f19f4ab2f38cfc794a238",
"reference": "1a37b2f1dd66d36c5b8f19f4ab2f38cfc794a238",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/6da284de7eeb57b7c120513998b712a718a3504a",
"reference": "6da284de7eeb57b7c120513998b712a718a3504a",
"shasum": ""
},
"require": {
@ -202,70 +202,7 @@
"profiler",
"webprofiler"
],
"time": "2014-10-07 14:21:49"
},
{
"name": "barryvdh/laravel-ide-helper",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-ide-helper.git",
"reference": "89a17fc7b9962d87cde29bf129c7942e9b1a4a8f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/89a17fc7b9962d87cde29bf129c7942e9b1a4a8f",
"reference": "89a17fc7b9962d87cde29bf129c7942e9b1a4a8f",
"shasum": ""
},
"require": {
"illuminate/console": "4.x|5.0.x",
"illuminate/filesystem": "4.x|5.0.x",
"illuminate/support": "4.x|5.0.x",
"php": ">=5.3.0",
"phpdocumentor/reflection-docblock": "2.0.x",
"symfony/class-loader": "~2.3"
},
"require-dev": {
"doctrine/dbal": "~2.3"
},
"suggest": {
"doctrine/dbal": "Load information from the database about models for phpdocs (~2.3)"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.11-dev"
}
},
"autoload": {
"psr-4": {
"Barryvdh\\LaravelIdeHelper\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.",
"keywords": [
"autocomplete",
"codeintel",
"helper",
"ide",
"laravel",
"netbeans",
"phpdoc",
"phpstorm",
"sublime"
],
"time": "2014-09-28 14:19:31"
"time": "2014-10-02 11:36:36"
},
{
"name": "chumper/datatable",
@ -401,479 +338,6 @@
"notification-url": "https://packagist.org/downloads/",
"time": "2014-01-17 12:21:18"
},
{
"name": "doctrine/annotations",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "6a6bec0670bb6e71a263b08bc1b98ea242928633"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/6a6bec0670bb6e71a263b08bc1b98ea242928633",
"reference": "6a6bec0670bb6e71a263b08bc1b98ea242928633",
"shasum": ""
},
"require": {
"doctrine/lexer": "1.*",
"php": ">=5.3.2"
},
"require-dev": {
"doctrine/cache": "1.*",
"phpunit/phpunit": "4.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Annotations\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Docblock Annotations Parser",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"annotations",
"docblock",
"parser"
],
"time": "2014-09-25 16:45:30"
},
{
"name": "doctrine/cache",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
"reference": "f7a1d660c521461b835dc31af0f6c9836769e917"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/f7a1d660c521461b835dc31af0f6c9836769e917",
"reference": "f7a1d660c521461b835dc31af0f6c9836769e917",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"conflict": {
"doctrine/common": ">2.2,<2.4"
},
"require-dev": {
"phpunit/phpunit": ">=3.7",
"satooshi/php-coveralls": "~0.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Cache\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Caching library offering an object-oriented API for many cache backends",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"cache",
"caching"
],
"time": "2014-09-29 13:28:56"
},
{
"name": "doctrine/collections",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
"reference": "8c5148e0ef8cee4afe86d45ba98f7b6d96e780d0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/collections/zipball/8c5148e0ef8cee4afe86d45ba98f7b6d96e780d0",
"reference": "8c5148e0ef8cee4afe86d45ba98f7b6d96e780d0",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Collections\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Collections Abstraction library",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"array",
"collections",
"iterator"
],
"time": "2014-09-24 12:11:27"
},
{
"name": "doctrine/common",
"version": "2.4.x-dev",
"source": {
"type": "git",
"url": "https://github.com/doctrine/common.git",
"reference": "ae92d076442e27b6910dd86a1292a8867cf5cfe4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/common/zipball/ae92d076442e27b6910dd86a1292a8867cf5cfe4",
"reference": "ae92d076442e27b6910dd86a1292a8867cf5cfe4",
"shasum": ""
},
"require": {
"doctrine/annotations": "1.*",
"doctrine/cache": "1.*",
"doctrine/collections": "1.*",
"doctrine/inflector": "1.*",
"doctrine/lexer": "1.*",
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "~3.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com",
"homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
}
],
"description": "Common Library for Doctrine projects",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"annotations",
"collections",
"eventmanager",
"persistence",
"spl"
],
"time": "2014-05-21 19:29:23"
},
{
"name": "doctrine/dbal",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "7175964c30f4fd54c90f6f9c7c6f7bf49fc1c939"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/7175964c30f4fd54c90f6f9c7c6f7bf49fc1c939",
"reference": "7175964c30f4fd54c90f6f9c7c6f7bf49fc1c939",
"shasum": ""
},
"require": {
"doctrine/common": "2.4.*",
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "4.0.*",
"symfony/console": "2.*"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
},
"bin": [
"bin/doctrine-dbal"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.5.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\DBAL\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
}
],
"description": "Database Abstraction Layer",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"database",
"dbal",
"persistence",
"queryobject"
],
"time": "2014-09-17 17:17:21"
},
{
"name": "doctrine/inflector",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "8a0b96e65d2399d6f95b75de11134843a2c61feb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/8a0b96e65d2399d6f95b75de11134843a2c61feb",
"reference": "8a0b96e65d2399d6f95b75de11134843a2c61feb",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "4.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Inflector\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Common String Manipulations with regard to casing and singular/plural rules.",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"inflection",
"pluralize",
"singularize",
"string"
],
"time": "2014-10-05 18:49:49"
},
{
"name": "doctrine/lexer",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Lexer\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"lexer",
"parser"
],
"time": "2014-09-09 13:34:57"
},
{
"name": "filp/whoops",
"version": "1.0.10",
@ -1203,7 +667,7 @@
"authors": [
{
"name": "Anthony Ferrara",
"email": "ircmaxell@php.net",
"email": "ircmaxell@ircmaxell.com",
"homepage": "http://blog.ircmaxell.com"
}
],
@ -1263,46 +727,6 @@
],
"time": "2013-10-09 04:20:00"
},
{
"name": "jsanc623/phpbenchtime",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/jsanc623/PHPBenchTime.git",
"reference": "e8cba5217fe5998ae1926c2cb2202d8d973db1f1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jsanc623/PHPBenchTime/zipball/e8cba5217fe5998ae1926c2cb2202d8d973db1f1",
"reference": "e8cba5217fe5998ae1926c2cb2202d8d973db1f1",
"shasum": ""
},
"type": "library",
"autoload": {
"psr-0": {
"": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Juan Sanchez",
"email": "juan.sanchez@juanleonardosanchez.com"
}
],
"description": "A light benchmark timer class for PHP.",
"keywords": [
"benchmark",
"benchtime",
"profiler",
"stopwatch",
"timer"
],
"time": "2014-07-23 20:52:24"
},
{
"name": "laravel/framework",
"version": "v4.1.25",
@ -1455,11 +879,11 @@
"name": "Max Ehsan",
"email": "contact@laravelbook.com",
"homepage": "http://laravelbook.com/",
"role": "Developer"
"role": "Maintainer"
},
{
"name": "Igor Santos",
"email": "igorsantos07@gmail.com",
"email": "igorsantos07+dev@gmail.com",
"homepage": "http://www.igorsantos.com.br",
"role": "Developer"
}
@ -2436,12 +1860,12 @@
"source": {
"type": "git",
"url": "https://github.com/thephpleague/omnipay-mollie.git",
"reference": "646a35bf726fd29f25df163ee1c9f37c811a3443"
"reference": "4d49e5600adc0990ced6ef368efa46883a9171fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/omnipay-mollie/zipball/646a35bf726fd29f25df163ee1c9f37c811a3443",
"reference": "646a35bf726fd29f25df163ee1c9f37c811a3443",
"url": "https://api.github.com/repos/thephpleague/omnipay-mollie/zipball/4d49e5600adc0990ced6ef368efa46883a9171fc",
"reference": "4d49e5600adc0990ced6ef368efa46883a9171fc",
"shasum": ""
},
"require": {
@ -2485,7 +1909,7 @@
"pay",
"payment"
],
"time": "2014-10-07 13:55:30"
"time": "2014-09-17 00:39:49"
},
{
"name": "omnipay/multisafepay",
@ -3462,55 +2886,6 @@
],
"time": "2014-06-23 09:37:18"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "fd0ac2007401505fb596fdfb859ec4e103d69e55"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/fd0ac2007401505fb596fdfb859ec4e103d69e55",
"reference": "fd0ac2007401505fb596fdfb859ec4e103d69e55",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"suggest": {
"dflydev/markdown": "~1.0",
"erusev/parsedown": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-0": {
"phpDocumentor": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "mike.vanriel@naenius.com"
}
],
"time": "2014-09-02 14:26:20"
},
{
"name": "phpseclib/phpseclib",
"version": "dev-master",
@ -3857,56 +3232,6 @@
"homepage": "http://symfony.com",
"time": "2014-09-22 08:51:05"
},
{
"name": "symfony/class-loader",
"version": "dev-master",
"target-dir": "Symfony/Component/ClassLoader",
"source": {
"type": "git",
"url": "https://github.com/symfony/ClassLoader.git",
"reference": "fe9ec2bf22e4279892ac3d83bc584e539a79fa41"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/ClassLoader/zipball/fe9ec2bf22e4279892ac3d83bc584e539a79fa41",
"reference": "fe9ec2bf22e4279892ac3d83bc584e539a79fa41",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"symfony/finder": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.6-dev"
}
},
"autoload": {
"psr-0": {
"Symfony\\Component\\ClassLoader\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
},
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Symfony ClassLoader Component",
"homepage": "http://symfony.com",
"time": "2014-10-01 05:53:11"
},
{
"name": "symfony/console",
"version": "2.4.x-dev",
@ -5217,12 +4542,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "f75e6b2e0764bcf4faa5082f4b60d5e7cf0959bb"
"reference": "5e18ee651da9c3254ad5105ad58da90f4a510e7d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f75e6b2e0764bcf4faa5082f4b60d5e7cf0959bb",
"reference": "f75e6b2e0764bcf4faa5082f4b60d5e7cf0959bb",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5e18ee651da9c3254ad5105ad58da90f4a510e7d",
"reference": "5e18ee651da9c3254ad5105ad58da90f4a510e7d",
"shasum": ""
},
"require": {
@ -5239,7 +4564,7 @@
"phpunit/phpunit-mock-objects": "2.4.*@dev",
"sebastian/comparator": "~1.0",
"sebastian/diff": "~1.1",
"sebastian/environment": "~1.1",
"sebastian/environment": "~1.0",
"sebastian/exporter": "~1.0",
"sebastian/global-state": "1.0.*@dev",
"sebastian/version": "~1.0",
@ -5280,7 +4605,7 @@
"testing",
"xunit"
],
"time": "2014-10-07 09:30:07"
"time": "2014-10-05 08:32:28"
},
{
"name": "phpunit/phpunit-mock-objects",
@ -5460,24 +4785,24 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "6288ebbf6fa3ed2b2ff2d69c356fbaaf4f0971a7"
"reference": "10c7467da0622f7848cc5cadc0828c3359254df4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6288ebbf6fa3ed2b2ff2d69c356fbaaf4f0971a7",
"reference": "6288ebbf6fa3ed2b2ff2d69c356fbaaf4f0971a7",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/10c7467da0622f7848cc5cadc0828c3359254df4",
"reference": "10c7467da0622f7848cc5cadc0828c3359254df4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.3"
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
"dev-master": "1.0.x-dev"
}
},
"autoload": {
@ -5492,7 +4817,8 @@
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
@ -5502,7 +4828,7 @@
"environment",
"hhvm"
],
"time": "2014-10-07 09:23:16"
"time": "2014-05-04 17:56:05"
},
{
"name": "sebastian/exporter",
@ -5575,12 +4901,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "231d48620efde984fd077ee92916099a3ece9a59"
"reference": "cd2f406aa90b591e1c45023c3a8d77edcb417bac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/231d48620efde984fd077ee92916099a3ece9a59",
"reference": "231d48620efde984fd077ee92916099a3ece9a59",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/cd2f406aa90b591e1c45023c3a8d77edcb417bac",
"reference": "cd2f406aa90b591e1c45023c3a8d77edcb417bac",
"shasum": ""
},
"require": {
@ -5618,7 +4944,7 @@
"keywords": [
"global state"
],
"time": "2014-10-06 09:49:11"
"time": "2014-09-04 07:21:11"
},
{
"name": "sebastian/version",

File diff suppressed because it is too large Load Diff

23
public/js/built.public.js Normal file
View File

@ -0,0 +1,23 @@
/* Copyright (C) 2012 Sylvain Hamel
Project: https://github.com/redhotsly/simple-expand
MIT Licence: https://raw.github.com/redhotsly/simple-expand/master/licence-mit.txt */
(function($){"use strict";function SimpleExpand(){var that=this;that.defaults={hideMode:"fadeToggle",defaultSearchMode:"parent",defaultTarget:".content",throwOnMissingTarget:true,keepStateInCookie:false,cookieName:"simple-expand"};that.settings={};$.extend(that.settings,that.defaults);that.findLevelOneDeep=function(parent,filterSelector,stopAtSelector){return parent.find(filterSelector).filter(function(){return!$(this).parentsUntil(parent,stopAtSelector).length})};that.setInitialState=function(expander,targets){var isExpanded=that.readState(expander);if(isExpanded){expander.removeClass("collapsed").addClass("expanded");that.show(targets)}else{expander.removeClass("expanded").addClass("collapsed");that.hide(targets)}};that.hide=function(targets){if(that.settings.hideMode==="fadeToggle"){targets.hide()}else if(that.settings.hideMode==="basic"){targets.hide()}};that.show=function(targets){if(that.settings.hideMode==="fadeToggle"){targets.show()}else if(that.settings.hideMode==="basic"){targets.show()}};that.checkKeepStateInCookiePreconditions=function(){if(that.settings.keepStateInCookie&&$.cookie===undefined){throw new Error("simple-expand: keepStateInCookie option requires $.cookie to be defined.")}};that.readCookie=function(){var jsonString=$.cookie(that.settings.cookieName);if(jsonString===null||jsonString===""){return{}}else{return JSON.parse(jsonString)}};that.readState=function(expander){if(!that.settings.keepStateInCookie){return expander.hasClass("expanded")}var id=expander.attr("Id");if(id===undefined){return}var cookie=that.readCookie();var cookieValue=cookie[id];if(typeof cookieValue!=="undefined"){return cookie[id]===true}else{return expander.hasClass("expanded")}};that.saveState=function(expander,isExpanded){if(!that.settings.keepStateInCookie){return}var id=expander.attr("Id");if(id===undefined){return}var cookie=that.readCookie();cookie[id]=isExpanded;$.cookie(that.settings.cookieName,JSON.stringify(cookie),{raw:true,path:window.location.pathname})};that.toggle=function(expander,targets){var isExpanded=that.toggleCss(expander);if(that.settings.hideMode==="fadeToggle"){targets.fadeToggle(150)}else if(that.settings.hideMode==="basic"){targets.toggle()}else if($.isFunction(that.settings.hideMode)){that.settings.hideMode(expander,targets,isExpanded)}that.saveState(expander,isExpanded);return false};that.toggleCss=function(expander){if(expander.hasClass("expanded")){expander.toggleClass("collapsed expanded");return false}else{expander.toggleClass("expanded collapsed");return true}};that.findTargets=function(expander,searchMode,targetSelector){var targets=[];if(searchMode==="absolute"){targets=$(targetSelector)}else if(searchMode==="relative"){targets=that.findLevelOneDeep(expander,targetSelector,targetSelector)}else if(searchMode==="parent"){var parent=expander.parent();do{targets=that.findLevelOneDeep(parent,targetSelector,targetSelector);if(targets.length===0){parent=parent.parent()}}while(targets.length===0&&parent.length!==0)}return targets};that.activate=function(jquery,options){$.extend(that.settings,options);that.checkKeepStateInCookiePreconditions();jquery.each(function(){var expander=$(this);var targetSelector=expander.attr("data-expander-target")||that.settings.defaultTarget;var searchMode=expander.attr("data-expander-target-search")||that.settings.defaultSearchMode;var targets=that.findTargets(expander,searchMode,targetSelector);if(targets.length===0){if(that.settings.throwOnMissingTarget){throw"simple-expand: Targets not found"}return this}that.setInitialState(expander,targets);expander.click(function(){return that.toggle(expander,targets)})})}}window.SimpleExpand=SimpleExpand;$.fn.simpleexpand=function(options){var instance=new SimpleExpand;instance.activate(this,options);return this}})(jQuery);
(function ($) {
$.fn.vAlign = function() {
return this.each(function(i){
$(this).children().wrapAll('<div class="nitinh-vAlign" style="position:relative;"></div>');
var div = $(this).children('div.nitinh-vAlign');
var ph = $(this).innerHeight();
var dh = div.height();
var mh = (ph - dh) / 2;
div.css('top', mh);
});
};
})(jQuery);
/*!
* Bootstrap v3.1.1 (http://getbootstrap.com)
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(this.transitioning||this.$element.hasClass("in"))return;var b=a.Event("show.bs.collapse");this.$element.trigger(b);if(b.isDefaultPrevented())return;var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])},b.prototype.hide=function(){if(this.transitioning||!this.$element.hasClass("in"))return;var b=a.Event("hide.bs.collapse");this.$element.trigger(b);if(b.isDefaultPrevented())return;var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};if(!a.support.transition)return d.call(this);this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350)},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),typeof c=="object"&&c);!e&&f.toggle&&c=="show"&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":c.data(),i=c.attr("data-parent"),j=i&&a(i);if(!g||!g.transitioning)j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(c).addClass("collapsed"),c[f.hasClass("in")?"addClass":"removeClass"]("collapsed");f.collapse(h)})}(jQuery),+function(a){function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(a.style[c]!==undefined)return{end:b[c]};return!1}"use strict",a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery)

5
public/js/d3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff