1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-19 16:01:34 +02:00

Implemented setup page

This commit is contained in:
Hillel Coren 2014-11-28 15:34:01 +02:00
parent a739429005
commit 2295a64bff
13 changed files with 520 additions and 264 deletions

View File

@ -47,17 +47,10 @@ Note: you may be prompted for your Github user/pass due to their API limits.
composer install
Install JavaScript and HTML packages using Bower
Install JavaScript and HTML packages using Bower. This is optional, it's only needed if you want to modify the JavaScript.
bower install
Create the development environment configurations
mkdir app/config/development
cp app/config/app.php app/config/development/
cp app/config/database.php app/config/development/
cp app/config/mail.php app/config/development/
Create database user and a database for ninja
CREATE SCHEMA `ninja` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
@ -65,11 +58,7 @@ Create database user and a database for ninja
GRANT ALL PRIVILEGES ON `ninja`.* TO 'ninja'@'localhost';
FLUSH PRIVILEGES;
Configure development/config/database.php and development/config/mail.php and initialize the database.
php artisan migrate --seed
Add public/ to your web server root
Add public/ to your web server root then load / to configure the application.
### Deleveloper Notes

View File

@ -13,7 +13,7 @@ return array(
|
*/
'debug' => true,
'debug' => false,
/*
|--------------------------------------------------------------------------

View File

@ -28,7 +28,7 @@ return array(
|
*/
'host' => '',
//'host' => '',
/*
|--------------------------------------------------------------------------

View File

@ -19,52 +19,6 @@ class AccountController extends \BaseController {
$this->contactMailer = $contactMailer;
}
public function install()
{
if (!Utils::isNinja() && !Schema::hasTable('accounts')) {
try {
Artisan::call('migrate');
Artisan::call('db:seed');
} catch (Exception $e) {
Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/');
}
public function update()
{
if (!Utils::isNinja()) {
try {
Artisan::call('migrate');
Cache::flush();
} catch (Exception $e) {
Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/');
}
/*
public function reset()
{
if (Utils::isNinjaDev()) {
Confide::logout();
try {
Artisan::call('migrate:reset');
Artisan::call('migrate');
Artisan::call('db:seed');
} catch (Exception $e) {
Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/');
}
*/
public function demo()
{
$demoAccountId = Utils::getDemoAccountId();
@ -114,7 +68,7 @@ class AccountController extends \BaseController {
}
Auth::login($user, true);
Event::fire('user.login');
Event::fire('user.login');
return Redirect::to('invoices/create');
}
@ -918,32 +872,7 @@ class AccountController extends \BaseController {
$user->registered = true;
$user->amend();
if (Utils::isNinja())
{
$this->userMailer->sendConfirmation($user);
}
else
{
/*
$url = NINJA_APP_URL . '/signup/register';
$data = '';
$fields = [
'first_name' => urlencode($user->first_name),
'last_name' => urlencode($user->last_name),
'email' => urlencode($user->email)
];
foreach($fields as $key=>$value) { $data .= $key.'='.$value.'&'; }
rtrim($data, '&');
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $data);
curl_exec($ch);
curl_close($ch);
*/
}
$this->userMailer->sendConfirmation($user);
$activities = Activity::scope()->get();
foreach ($activities as $activity)

View File

@ -0,0 +1,202 @@
<?php
use ninja\mailers\Mailer;
use ninja\repositories\AccountRepository;
class AppController extends BaseController {
protected $accountRepo;
protected $mailer;
public function __construct(AccountRepository $accountRepo, Mailer $mailer)
{
parent::__construct();
$this->accountRepo = $accountRepo;
$this->mailer = $mailer;
}
public function showSetup()
{
if (Utils::isNinja() || Utils::isDatabaseSetup())
{
return Redirect::to('/');
}
return View::make('setup');
}
public function doSetup()
{
if (Utils::isNinja() || Utils::isDatabaseSetup())
{
return Redirect::to('/');
}
$valid = false;
$test = Input::get('test');
$app = Input::get('app');
$app['key'] = str_random(RANDOM_KEY_LENGTH);
$database = Input::get('database');
$dbType = $database['default'];
$database[$dbType] = $database['type'];
unset($database['type']);
$mail = Input::get('mail');
$email = $mail['username'];
$mail['from']['address'] = $email;
if ($test == 'mail')
{
return self::testMail($mail);
}
$valid = self::testDatabase($database);
if ($test == 'db')
{
return $valid ? 'Success' : 'Failed';
}
else if (!$valid)
{
return Redirect::to('/setup')->withInput();
}
$configDir = app_path() . '/config/production';
if (!file_exists($configDir))
{
mkdir($configDir);
}
foreach(['app' => $app, 'database' => $database, 'mail' => $mail] as $key => $config)
{
$content = '<?php return ' . var_export($config, true) . ';';
$fp = fopen(app_path() . "/config/production/{$key}.php" , 'w');
fwrite($fp, $content);
fclose($fp);
}
Artisan::call('migrate');
Artisan::call('db:seed');
$account = $this->accountRepo->create();
$user = $account->users()->first();
$user->first_name = trim(Input::get('first_name'));
$user->last_name = trim(Input::get('last_name'));
$user->email = trim(strtolower(Input::get('email')));
$user->username = $user->email;
$user->password = trim(Input::get('password'));
$user->password_confirmation = trim(Input::get('password'));
$user->registered = true;
$user->amend();
//Auth::login($user, true);
//self::register($user);
return Redirect::to('/invoices/create');
}
private function testDatabase($database)
{
$dbType = $database['default'];
Config::set('database.default', $dbType);
foreach ($database[$dbType] as $key => $val)
{
Config::set("database.connections.{$dbType}.{$key}", $val);
}
try
{
$valid = DB::connection()->getDatabaseName() ? true : false;
}
catch (Exception $e)
{
return $e->getMessage();
}
return $valid;
}
private function testMail($mail)
{
$email = $mail['username'];
$fromName = $mail['from']['name'];
foreach ($mail as $key => $val)
{
Config::set("mail.{$key}", $val);
}
Config::set('mail.from.address', $email);
Config::set('mail.from.name', $fromName);
$data = [
'text' => 'Test email'
];
try
{
$this->mailer->sendTo($email, $email, $fromName, 'Test email', 'contact', $data);
return 'Sent';
}
catch (Exception $e)
{
return $e->getMessage();
}
}
private function register($user)
{
$url = NINJA_APP_URL . '/signup/register';
$data = '';
$fields = [
'first_name' => urlencode($user->first_name),
'last_name' => urlencode($user->last_name),
'email' => urlencode($user->email)
];
foreach($fields as $key=>$value) { $data .= $key.'='.$value.'&'; }
rtrim($data, '&');
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $data);
curl_exec($ch);
curl_close($ch);
}
public function install()
{
if (!Utils::isNinja() && !Utils::isDatabaseSetup()) {
try {
Artisan::call('migrate');
Artisan::call('db:seed');
} catch (Exception $e) {
Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/');
}
public function update()
{
if (!Utils::isNinja()) {
try {
Artisan::call('migrate');
Cache::flush();
} catch (Exception $e) {
Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/');
}
}

View File

@ -4,7 +4,6 @@ use ninja\mailers\Mailer;
class HomeController extends BaseController {
protected $layout = 'master';
protected $mailer;
public function __construct(Mailer $mailer)
@ -22,7 +21,11 @@ class HomeController extends BaseController {
}
else
{
if (Account::count() == 0)
if (!Utils::isDatabaseSetup())
{
return Redirect::to('/setup');
}
else if (Account::count() == 0)
{
return Redirect::to('/invoice_now');
}

View File

@ -13,6 +13,7 @@
App::before(function($request)
{
// Ensure all request are over HTTPS in production
if (App::environment() == ENV_PRODUCTION)
{
if (!Request::secure())
@ -21,12 +22,18 @@ App::before(function($request)
}
}
// If the database doens't yet exist we'll skip the rest
if (!Utils::isNinja() && !Utils::isDatabaseSetup())
{
return;
}
// check the application is up to date and for any news feed messages
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()) {
@ -56,6 +63,7 @@ App::before(function($request)
}
}
// Check if we're requesting to change the account's language
if (Input::has('lang'))
{
$locale = Input::get('lang');
@ -78,6 +86,13 @@ App::before(function($request)
App::setLocale($locale);
}
// Make sure the account/user localization settings are in the session
if (Auth::check() && !Session::has(SESSION_TIMEZONE))
{
Event::fire('user.refresh');
}
// Check if the user is claiming a license (ie, additional invoices, white label, etc.)
$claimingLicense = Utils::startsWith($_SERVER['REQUEST_URI'], '/claim_license');
if (!$claimingLicense && Input::has('license_key') && Input::has('product_id'))
{

View File

@ -12,6 +12,21 @@ class Utils
return Auth::check() && Auth::user()->confirmed;
}
public static function isDatabaseSetup()
{
try
{
if (Schema::hasTable('accounts'))
{
return true;
}
}
catch (Exception $e)
{
return false;
}
}
public static function isProd()
{
return App::environment() == ENV_PRODUCTION;

View File

@ -17,7 +17,7 @@ class Mailer {
$replyEmail = $fromEmail;
// http://stackoverflow.com/questions/2421234/gmail-appearing-to-ignore-reply-to
if ($toEmail != CONTACT_EMAIL)
if (Utils::isNinja() && $toEmail != CONTACT_EMAIL)
{
$fromEmail = NINJA_FROM_EMAIL;
}

View File

@ -1,13 +1,5 @@
<?php
/*
$content = "some text here";
$fp = fopen("../myText.txt","wb");
fwrite($fp,$content);
fclose($fp);
*/
/*
|--------------------------------------------------------------------------
| Application Routes
@ -19,9 +11,8 @@ fclose($fp);
|
*/
//apc_clear_cache();
//Cache::flush();
//apc_clear_cache();
//dd(DB::getQueryLog());
//dd(Client::getPrivateId(1));
//dd(new DateTime());
@ -30,10 +21,13 @@ fclose($fp);
//dd(gethostname());
//Log::error('test');
Route::get('install', 'AccountController@install');
Route::get('update', 'AccountController@update');
Route::get('reset', 'AccountController@reset');
// Application setup
Route::get('setup', 'AppController@showSetup');
Route::post('setup', 'AppController@doSetup');
Route::get('install', 'AppController@install');
Route::get('update', 'AppController@update');
// Public pages
Route::get('/', 'HomeController@showIndex');
Route::get('/rocksteady', 'HomeController@showIndex');
Route::get('/about', 'HomeController@showAboutUs');
@ -399,14 +393,9 @@ function otrans($text)
}
}
if (Auth::check() && !Session::has(SESSION_TIMEZONE))
{
Event::fire('user.refresh');
}
Validator::extend('positive', function($attribute, $value, $parameters)
{
return Utils::parseFloat($value) > 0;
return Utils::parseFloat($value) > 0;
});
Validator::extend('has_credit', function($attribute, $value, $parameters)

View File

@ -20,7 +20,7 @@
<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">
<link href="{{ asset('favicon.ico') }}" rel="icon" type="image/x-icon">
<link rel="canonical" href="{{ NINJA_APP_URL }}/{{ Request::path() }}"></link>
<script src="{{ asset('built.js') }}?no_cache={{ NINJA_VERSION }}" type="text/javascript"></script>

View File

@ -18,7 +18,7 @@
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-3 center-block">
@ -31,7 +31,7 @@
</div>
</div>
</section>
<section class="features-splash">
@ -73,166 +73,166 @@
</div>
</section>
<section class="features-splash customContainer">
<div class="container">
<div class="row col-md-12">
<div class="col-md-5 col-md-offset-4 customFontHead">
<div class="col-md-12">
<span class="glyphicon glyphicon-ok"></span>
</div>
<div class="col-md-12 customTextBorder">
Invoice Ninja Does Everything You'd Expect Your Online Invoicing App to Do
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/InvoiceClientsViaEmail.png') }}"></span>
<span class="customSubMenu shiftLeft"> Invoice clients via email </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/InTuitiveEditingInterface.png') }}"></span>
<span class="customSubMenu shiftLeft"> Intuitive editing interface</span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/PrintablePDFInvoices.png') }}"></span>
<span class="customSubMenu shiftLeft"> Printable .pdf invoices</span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/MultipleTaxSettings.png') }}"></span>
<span class="customSubMenu shiftLeft"> Multiple tax settings</span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/ImportExportRecords.png') }}"></span>
<span class="customSubMenu shiftLeft"> Import/export records </span>
</div>
</div>
<div class="col-md-2 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/AcceptPaymentsOnline.png') }}"></span>
<span class="customSubMenu shiftLeft"> Accept payments online</span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/BestInClassSecurity.png') }}"></span>
<span class="customSubMenu shiftLeft"> Best-in-class security </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/AdjustablePaymentTerms.png') }}"></span>
<span class="customSubMenu shiftLeft"> Adjustable payment terms </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/MultipleCurrencySupport.png') }}"></span>
<span class="customSubMenu shiftLeft"> Multiple currency support </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/RecurringInvoiceProfiles.png') }}"></span>
<span class="customSubMenu shiftLeft"> Recurring invoice profiles </span>
</div>
</div>
<div class="col-md-2 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/FreeInvoicing.png') }}"></span>
<span class="customSubMenu shiftLeft"> Free invoicing platform </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/EstimatesProForma.png') }}"></span>
<span class="customSubMenu shiftLeft"> Estimates & pro-forma </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/PaymentTracking.png') }}"></span>
<span class="customSubMenu shiftLeft"> Payment tracking </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/MultilingualSupport.png') }}"></span>
<span class="customSubMenu shiftLeft"> Multilingual support </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/SelfHostedAvailable.png') }}"></span>
<span class="customSubMenu shiftLeft"> Self-hosted available </span>
</div>
</div>
<div class="col-md-2 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/LivePDFCreation.png') }}"></span>
<span class="customSubMenu shiftLeft"> Live .pdf creation </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/CloneInvoices.png') }}"></span>
<span class="customSubMenu shiftLeft"> Clone invoices </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/CloudBasedApp.png') }}"></span>
<span class="customSubMenu shiftLeft"> Cloud-based app </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/OpenSource.png') }}"></span>
<span class="customSubMenu shiftLeft"> Open source </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/BeautifulTemplates.png') }}"></span>
<span class="customSubMenu shiftLeft"> Beautiful templates </span>
</div>
</div>
<div class="col-md-4 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/CustomizeInvoices.png') }}"></span>
<span class="customSubMenu shiftLeft"> Cutomize invoices with your company logo </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/PersonalizeInvoiceColor.png') }}"></span>
<span class="customSubMenu shiftLeft"> Personalize invoice color schemes </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/InvoiceClientsViaEmail.png') }}"></span>
<span class="customSubMenu shiftLeft"> Alerts when invoices are viewed or paid </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/IntegrateWithPaymentGateways.png') }}"></span>
<span class="customSubMenu shiftLeft"> Integrate with top payment gateways </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/ManualAutomaticInvoiceNumbers.png') }}"></span>
<span class="customSubMenu shiftLeft"> Manual or automatic invoice numbers </span>
</div>
</div>
</div>
</div>
</section>
<div class="container">
<div class="row col-md-12">
<div class="col-md-5 col-md-offset-4 customFontHead">
<div class="col-md-12">
<span class="glyphicon glyphicon-ok"></span>
</div>
<div class="col-md-12 customTextBorder">
Invoice Ninja Does Everything You'd Expect Your Online Invoicing App to Do
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/InvoiceClientsViaEmail.png') }}"></span>
<span class="customSubMenu shiftLeft"> Invoice clients via email </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/InTuitiveEditingInterface.png') }}"></span>
<span class="customSubMenu shiftLeft"> Intuitive editing interface</span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/PrintablePDFInvoices.png') }}"></span>
<span class="customSubMenu shiftLeft"> Printable .pdf invoices</span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/MultipleTaxSettings.png') }}"></span>
<span class="customSubMenu shiftLeft"> Multiple tax settings</span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/ImportExportRecords.png') }}"></span>
<span class="customSubMenu shiftLeft"> Import/export records </span>
</div>
</div>
<div class="col-md-2 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/AcceptPaymentsOnline.png') }}"></span>
<span class="customSubMenu shiftLeft"> Accept payments online</span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/BestInClassSecurity.png') }}"></span>
<span class="customSubMenu shiftLeft"> Best-in-class security </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/AdjustablePaymentTerms.png') }}"></span>
<span class="customSubMenu shiftLeft"> Adjustable payment terms </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/MultipleCurrencySupport.png') }}"></span>
<span class="customSubMenu shiftLeft"> Multiple currency support </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/RecurringInvoiceProfiles.png') }}"></span>
<span class="customSubMenu shiftLeft"> Recurring invoice profiles </span>
</div>
</div>
<div class="col-md-2 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/FreeInvoicing.png') }}"></span>
<span class="customSubMenu shiftLeft"> Free invoicing platform </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/EstimatesProForma.png') }}"></span>
<span class="customSubMenu shiftLeft"> Estimates & pro-forma </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/PaymentTracking.png') }}"></span>
<span class="customSubMenu shiftLeft"> Payment tracking </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/MultilingualSupport.png') }}"></span>
<span class="customSubMenu shiftLeft"> Multilingual support </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/SelfHostedAvailable.png') }}"></span>
<span class="customSubMenu shiftLeft"> Self-hosted available </span>
</div>
</div>
<div class="col-md-2 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/LivePDFCreation.png') }}"></span>
<span class="customSubMenu shiftLeft"> Live .pdf creation </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/CloneInvoices.png') }}"></span>
<span class="customSubMenu shiftLeft"> Clone invoices </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/CloudBasedApp.png') }}"></span>
<span class="customSubMenu shiftLeft"> Cloud-based app </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/OpenSource.png') }}"></span>
<span class="customSubMenu shiftLeft"> Open source </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/BeautifulTemplates.png') }}"></span>
<span class="customSubMenu shiftLeft"> Beautiful templates </span>
</div>
</div>
<div class="col-md-4 customMenuOne">
<div class="customMenuDiv">
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/CustomizeInvoices.png') }}"></span>
<span class="customSubMenu shiftLeft"> Cutomize invoices with your company logo </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/PersonalizeInvoiceColor.png') }}"></span>
<span class="customSubMenu shiftLeft"> Personalize invoice color schemes </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/InvoiceClientsViaEmail.png') }}"></span>
<span class="customSubMenu shiftLeft"> Alerts when invoices are viewed or paid </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/IntegrateWithPaymentGateways.png') }}"></span>
<span class="customSubMenu shiftLeft"> Integrate with top payment gateways </span>
</div>
<div class="customMenuDiv" >
<span class="img-wrap shiftLeft" ><img src="{{ asset('images/ManualAutomaticInvoiceNumbers.png') }}"></span>
<span class="customSubMenu shiftLeft"> Manual or automatic invoice numbers </span>
</div>
</div>
</div>
</div>
</section>
<section class="blue">
<div class="container">
<div class="row">
<div class="col-md-5">
<h1>{{ trans('public.home.footer') }}</h1>
<div class="row">
<div class="col-md-7">
<a href="#">
<div class="cta">
<h2 onclick="return getStarted()">{{ trans('public.invoice_now') }} <span>+</span></h2>
</div>
</a>
<h1>{{ trans('public.home.footer') }}</h1>
<div class="row">
<div class="col-md-7">
<a href="#">
<div class="cta">
<h2 onclick="return getStarted()">{{ trans('public.invoice_now') }} <span>+</span></h2>
</div>
</a>
</div>
</div>
<p>{{ trans('public.no_signup_needed') }}</p>
</div>
<div class="col-md-7">
<img src="{{ asset('images/devices.png') }}">
</div>
<p>{{ trans('public.no_signup_needed') }}</p>
</div>
<div class="col-md-7">
<img src="{{ asset('images/devices.png') }}">
</div>
</div>
</div>
</section>

114
app/views/setup.blade.php Normal file
View File

@ -0,0 +1,114 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Invoice Ninja | Setup</title>
<meta charset="utf-8">
<meta name="csrf-token" content="<?= csrf_token() ?>">
<script src="{{ asset('built.js') }}?no_cache={{ NINJA_VERSION }}" type="text/javascript"></script>
<link href="{{ asset('built.public.css') }}?no_cache={{ NINJA_VERSION }}" rel="stylesheet" type="text/css"/>
</head>
<body>
<div class="container">
&nbsp;
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="jumbotron">
<h2>Invoice Ninja Setup</h2>
<p>
<pre>-- Commands to create a MySQL database and user
CREATE SCHEMA `ninja` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE USER 'ninja'@'localhost' IDENTIFIED BY 'ninja';
GRANT ALL PRIVILEGES ON `ninja`.* TO 'ninja'@'localhost';
FLUSH PRIVILEGES;</pre>
</p>
If you need help you can either post to our <a href="https://groups.google.com/forum/#!forum/invoiceninja" target="_blank">Google Group</a>
or email us at <a href="mailto:contact@invoiceninja.com" target="_blank">contact@invoiceninja.com</a>.
</div>
{{ Former::open() }}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Application Settings</h3>
</div>
<div class="panel-body">
{{ Former::text('app[url]')->label('URL')->value(Request::root()) }}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Database Connection</h3>
</div>
<div class="panel-body">
{{ Former::select('database[default]')->label('Driver')->options(['mysql' => 'MySQL', 'pgsql' => 'PostgreSQL', 'sqlite' => 'SQLite']) }}
{{ Former::text('database[type][host]')->label('Host')->value('localhost') }}
{{ Former::text('database[type][database]')->label('Database')->value('ninja') }}
{{ Former::text('database[type][username]')->label('Username')->value('ninja') }}
{{ Former::text('database[type][password]')->label('Password')->value('ninja') }}
{{ Former::actions( Button::normal('Test connection', ['onclick' => 'testDatabase()']), '&nbsp;&nbsp;<span id="dbTestResult"/>' ) }}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Email Settings</h3>
</div>
<div class="panel-body">
{{ Former::select('mail[driver]')->label('Driver')->options(['smtp' => 'SMTP', 'mail' => 'Mail', 'sendmail' => 'Sendmail']) }}
{{ Former::text('mail[host]')->label('Host')->value('localhost') }}
{{ Former::text('mail[port]')->label('Port')->value('587') }}
{{ Former::select('mail[encryption]')->label('Encryption')->options(['tls' => 'TLS', 'ssl' => 'SSL']) }}
{{ Former::text('mail[from][name]')->label('From Name') }}
{{ Former::text('mail[username]')->label('Email') }}
{{ Former::text('mail[password]')->label('Password') }}
{{ Former::actions( Button::normal('Send test email', ['onclick' => 'testMail()']), '&nbsp;&nbsp;<span id="mailTestResult"/>' ) }}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">User Details</h3>
</div>
<div class="panel-body">
{{ Former::text('first_name') }}
{{ Former::text('last_name') }}
{{ Former::text('email') }}
{{ Former::text('password') }}
</div>
</div>
{{ Former::actions( Button::submit_lg('Submit') ) }}
{{ Former::close() }}
</div>
<script type="text/javascript">
function testDatabase()
{
$('#dbTestResult').html('Working...').css('color', 'black');
var data = $("form").serialize() + "&test=db";
$.post( "/setup", data, function( data ) {
$('#dbTestResult').html(data).css('color', data == 'Success' ? 'green' : 'red');
});
}
function testMail()
{
$('#mailTestResult').html('Working...').css('color', 'black');
var data = $("form").serialize() + "&test=mail";
$.post( "/setup", data, function( data ) {
$('#mailTestResult').html(data).css('color', data == 'Sent' ? 'green' : 'red');
});
}
</script>
</body>
</html>