1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-05 18:52:44 +01:00

Merge branch 'v2' into v2

This commit is contained in:
David Bomba 2020-06-16 14:01:55 +10:00 committed by GitHub
commit 9fa069e884
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 693 additions and 428 deletions

View File

@ -64,9 +64,9 @@ class PortalComposer
$data[] = [ 'title' => ctrans('texts.invoices'), 'url' => 'client.invoices.index', 'icon' => 'file-text'];
$data[] = [ 'title' => ctrans('texts.recurring_invoices'), 'url' => 'client.recurring_invoices.index', 'icon' => 'file'];
$data[] = [ 'title' => ctrans('texts.payments'), 'url' => 'client.payments.index', 'icon' => 'credit-card'];
$data[] = [ 'title' => ctrans('texts.payment_methods'), 'url' => 'client.payment_methods.index', 'icon' => 'shield'];
$data[] = [ 'title' => ctrans('texts.quotes'), 'url' => 'client.quotes.index', 'icon' => 'align-left'];
$data[] = [ 'title' => ctrans('texts.credits'), 'url' => 'client.credits.index', 'icon' => 'credit-card'];
$data[] = [ 'title' => ctrans('texts.payment_methods'), 'url' => 'client.payment_methods.index', 'icon' => 'shield'];
return $data;
}

View File

@ -507,4 +507,9 @@ class Client extends BaseModel implements HasLocalePreference
return $defaults;
}
public function payments()
{
return $this->hasMany(Payment::class);
}
}

View File

@ -35,6 +35,7 @@ class SystemLog extends Model
const TYPE_STRIPE = 301;
const TYPE_LEDGER = 302;
const TYPE_FAILURE = 303;
const TYPE_CHECKOUT = 304;
const TYPE_QUOTA_EXCEEDED = 400;
const TYPE_UPSTREAM_FAILURE = 401;

View File

@ -0,0 +1,42 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\PaymentDrivers\CheckoutCom;
trait Utilities
{
public function getPublishableKey()
{
return $this->company_gateway->getConfigField('publicApiKey');
}
public function convertToCheckoutAmount($amount, $currency)
{
$cases = [
'option_1' => ['BIF', 'DJF', 'GNF', 'ISK', 'KMF', 'XAF', 'CLF', 'XPF', 'JPY', 'PYG', 'RWF', 'KRW', 'VUV', 'VND', 'XOF'],
'option_2' => ['BHD', 'IQD', 'JOD', 'KWD', 'LYD', 'OMR', 'TND'],
];
// https://docs.checkout.com/resources/calculating-the-value#Calculatingthevalue-Option1:Thefullvaluefullvalue
if (in_array($currency, $cases['option_1'])) {
return round($amount);
}
// https://docs.checkout.com/resources/calculating-the-value#Calculatingthevalue-Option2:Thevaluedividedby1000valuediv1000
if (in_array($currency, $cases['option_2'])) {
return round($amount * 1000);
}
// https://docs.checkout.com/resources/calculating-the-value#Calculatingthevalue-Option3:Thevaluedividedby100valuediv100
return round($amount * 100);
}
}

View File

@ -0,0 +1,276 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\PaymentDrivers;
use App\Events\Payment\PaymentWasCreated;
use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\CheckoutCom\Utilities;
use App\Utils\Traits\SystemLogTrait;
use Checkout\CheckoutApi;
use Checkout\Library\Exceptions\CheckoutHttpException;
use Checkout\Models\Payments\IdSource;
use Checkout\Models\Payments\Payment as CheckoutPayment;
use Checkout\Models\Payments\TokenSource;
class CheckoutComPaymentDriver extends BasePaymentDriver
{
use SystemLogTrait, Utilities;
/* The company gateway instance*/
public $company_gateway;
/* The Invitation */
protected $invitation;
/* Gateway capabilities */
protected $refundable = true;
/* Token billing */
protected $token_billing = true;
/* Authorise payment methods */
protected $can_authorise_credit_card = true;
/** Instance of \Checkout\CheckoutApi */
public $gateway;
/** Since with Checkout.com we handle only credit cards, this method should be empty. */
public function setPaymentMethod($string = null)
{
return $this;
}
public function init()
{
$config = [
'secret' => $this->company_gateway->getConfigField('secretApiKey'),
'public' => $this->company_gateway->getConfigField('publicApiKey'),
'sandbox' => $this->company_gateway->getConfigField('testMode'),
];
$this->gateway = new CheckoutApi($config['secret'], $config['sandbox'], $config['public']);
}
public function viewForType($gateway_type_id)
{
if ($gateway_type_id == GatewayType::CREDIT_CARD) {
return 'gateways.checkout.credit_card';
}
if ($gateway_type_id == GatewayType::TOKEN) {
return 'gateways.checkout.credit_card';
}
}
public function processPaymentView(array $data)
{
$data['gateway'] = $this;
$data['client'] = $this->client;
$data['currency'] = $this->client->getCurrencyCode();
$data['value'] = $this->convertToCheckoutAmount($data['amount_with_fee'], $this->client->getCurrencyCode());
$data['raw_value'] = $data['amount_with_fee'];
$data['customer_email'] = $this->client->present()->email;
return render($this->viewForType($data['payment_method_id']), $data);
}
public function processPaymentResponse($request)
{
$this->init();
$state = [
'server_response' => json_decode($request->gateway_response),
'value' => $request->value,
'raw_value' => $request->raw_value,
'currency' => $request->currency,
];
$state = array_merge($state, $request->all());
$state['store_card'] = boolval($state['store_card']);
if ($request->has('token') && !is_null($request->token)) {
$method = new IdSource($state['token']);
$payment = new CheckoutPayment($method, $state['currency']);
$payment->capture = false;
$payment->amount = $state['value'];
} else {
$method = new TokenSource($state['server_response']->cardToken);
$payment = new CheckoutPayment($method, $state['currency']);
$payment->amount = $state['value'];
if ($this->client->currency()->code === 'EUR') {
$payment->{"3ds"} = ['enabled' => true];
}
}
try {
$response = $this->gateway->payments()->request($payment);
$state['payment_response'] = $response;
if ($response->status === 'Authorized') {
return $this->processSuccessfulPayment($state);
}
if ($response->status === 'Pending') {
return $this->processPendingPayment($state);
}
if ($response->status === 'Declined') {
return $this->processUnsuccessfulPayment($state);
}
} catch (CheckoutHttpException $e) {
return $this->processInternallyFailedPayment($e, $state);
}
}
public function processSuccessfulPayment($state)
{
$state['charge_id'] = $state['payment_response']->id;
if (isset($state['store_card']) && $state['store_card']) {
$this->saveCard($state);
}
$data = [
'payment_method' => $state['charge_id'],
'payment_type' => PaymentType::parseCardType($state['payment_response']->source['scheme']),
'amount' => $state['raw_value'],
];
$payment = $this->createPayment($data, Payment::STATUS_COMPLETED);
$this->attachInvoices($payment, $state['hashed_ids']);
$payment->service()->updateInvoicePayment();
event(new PaymentWasCreated($payment, $payment->company));
$logger_message = [
'server_response' => $state['payment_response'],
'data' => $data
];
SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_CHECKOUT, $this->client);
return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
}
public function processPendingPayment($state)
{
$state['charge_id'] = $state['payment_response']->id;
if (isset($state['store_card']) && $state['store_card']) {
$this->saveCard($state);
}
$data = [
'payment_method' => $state['charge_id'],
'payment_type' => PaymentType::parseCardType($state['payment_response']->source['scheme']),
'amount' => $state['raw_value'],
];
$payment = $this->createPayment($data, Payment::STATUS_PENDING);
$this->attachInvoices($payment, $state['hashed_ids']);
$payment->service()->updateInvoicePayment();
event(new PaymentWasCreated($payment, $payment->company));
$logger_message = [
'server_response' => $state['payment_response'],
'data' => $data
];
SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_CHECKOUT, $this->client);
try {
return redirect($state['payment_response']->_links['redirect']['href']);
} catch (\Exception $e) {
SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_CHECKOUT, $this->client);
throw new \Exception('Failed to process the payment.', 1);
}
}
public function processUnsuccessfulPayment($state)
{
PaymentFailureMailer::dispatch($this->client, $state['payment_response']->response_summary, $this->client->company, $state['payment_response']->amount);
$message = [
'server_response' => $state['server_response'],
'data' => $state,
];
SystemLogger::dispatch($message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_CHECKOUT, $this->client);
throw new \Exception('Failed to process the payment: ' . $state['payment_response']->response_summary, 1);
}
public function processInternallyFailedPayment($e, $state)
{
$message = json_decode($e->getBody());
PaymentFailureMailer::dispatch($this->client, $message->error_type, $this->client->company, $state['value']);
$message = [
'server_response' => $state['server_response'],
'data' => $message,
];
SystemLogger::dispatch($message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_CHECKOUT, $this->client);
throw new \Exception('Failed to process the payment.', 1);
}
public function createPayment($data, $status = Payment::STATUS_COMPLETED): Payment
{
$payment = parent::createPayment($data, $status);
$client_contact = $this->getContact();
$client_contact_id = $client_contact ? $client_contact->id : null;
$payment->amount = $data['amount'];
$payment->type_id = $data['payment_type'];
$payment->transaction_reference = $data['payment_method'];
$payment->client_contact_id = $client_contact_id;
$payment->save();
return $payment;
}
public function saveCard($state)
{
$company_gateway_token = new ClientGatewayToken();
$company_gateway_token->company_id = $this->client->company->id;
$company_gateway_token->client_id = $this->client->id;
$company_gateway_token->token = $state['payment_response']->source['id'];
$company_gateway_token->company_gateway_id = $this->company_gateway->id;
$company_gateway_token->gateway_type_id = $state['payment_method_id'];
$company_gateway_token->meta = $state['payment_response']->source;
$company_gateway_token->save();
if ($this->client->gateway_tokens->count() == 1) {
$this->client->gateway_tokens()->update(['is_default' => 0]);
$company_gateway_token->is_default = 1;
$company_gateway_token->save();
}
}
}

View File

@ -1,139 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\PaymentDrivers;
use App\Factory\PaymentFactory;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use App\Models\Invoice;
use App\Models\Payment;
use App\Utils\Traits\SystemLogTrait;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Omnipay\Omnipay;
/**
* Class BasePaymentDriver
* @package App\PaymentDrivers
*
* Minimum dataset required for payment gateways
*
* $data = [
'amount' => $invoice->getRequestedAmount(),
'currency' => $invoice->getCurrencyCode(),
'returnUrl' => $completeUrl,
'cancelUrl' => $this->invitation->getLink(),
'description' => trans('texts.' . $invoice->getEntityType()) . " {$invoice->number}",
'transactionId' => $invoice->number,
'transactionType' => 'Purchase',
'clientIp' => Request::getClientIp(),
];
*/
class CheckoutPaymentDriver extends BasePaymentDriver
{
use SystemLogTrait;
/* The company gateway instance*/
protected $company_gateway;
/* The Omnipay payment driver instance*/
protected $gateway;
/* The Invitation */
protected $invitation;
/* Gateway capabilities */
protected $refundable = true;
/* Token billing */
protected $token_billing = true;
/* Authorise payment methods */
protected $can_authorise_credit_card = true;
public function createTransactionToken($amount)
{
// if ($this->invoice()->getCurrencyCode() == 'BHD') {
// $amount = $this->invoice()->getRequestedAmount() / 10;
// } elseif ($this->invoice()->getCurrencyCode() == 'KWD') {
// $amount = $this->invoice()->getRequestedAmount() * 10;
// } elseif ($this->invoice()->getCurrencyCode() == 'OMR') {
// $amount = $this->invoice()->getRequestedAmount();
// } else
// $amount = $this->invoice()->getRequestedAmount();
$response = $this->gateway()->purchase([
'amount' => $amount,
'currency' => $this->client->getCurrencyCode(),
])->send();
if ($response->isRedirect()) {
$token = $response->getTransactionReference();
session()->flash('transaction_reference', $token);
// On each request, session()->flash() || sesion('', value) || session[name] ||session->flash(key, value)
return $token;
}
return false;
}
public function viewForType($gateway_type_id)
{
switch ($gateway_type_id) {
case GatewayType::CREDIT_CARD:
return 'gateways.checkout.credit_card';
break;
case GatewayType::TOKEN:
break;
default:
break;
}
}
/**
*
* $data = [
'invoices' => $invoices,
'amount' => $amount,
'fee' => $gateway->calcGatewayFee($amount),
'amount_with_fee' => $amount + $gateway->calcGatewayFee($amount),
'token' => auth()->user()->client->gateway_token($gateway->id, $payment_method_id),
'payment_method_id' => $payment_method_id,
'hashed_ids' => explode(",", request()->input('hashed_ids')),
];
*/
public function processPaymentView(array $data)
{
$data['token'] = $this->createTransactionToken($data['amount']);
$data['gateway'] = $this->gateway();
return render($this->viewForType($data['payment_method_id']), $data);
}
public function processPaymentResponse($request)
{
$data['token'] = session('transaction_reference');
$this->completeOffsitePurchase($data);
}
}

View File

@ -1,5 +1,15 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\PaymentDrivers\Stripe;
trait Utilities

View File

@ -21,8 +21,8 @@
"php": ">=7.3",
"ext-json": "*",
"asgrim/ofxparser": "^1.2",
"checkout/checkout-sdk-php": "^1.0",
"authorizenet/authorizenet": "^2.0",
"beganovich/omnipay-checkout": "dev-master",
"cleverit/ubl_invoice": "^1.3",
"composer/composer": "^1.10",
"czproject/git-php": "^3.17",
@ -80,7 +80,8 @@
"App\\": "app/"
},
"files": [
"app/Libraries/OFX.php" ]
"app/Libraries/OFX.php"
]
},
"autoload-dev": {
"psr-4": {
@ -89,8 +90,7 @@
},
"extra": {
"laravel": {
"dont-discover": [
]
"dont-discover": []
}
},
"scripts": {

94
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6441fc634b3600e7099ae8c02d6230b0",
"content-hash": "5197c11f0679bd4daff4669e74c36f9d",
"packages": [
{
"name": "asgrim/ofxparser",
@ -191,30 +191,29 @@
"time": "2020-06-12T18:16:31+00:00"
},
{
"name": "beganovich/omnipay-checkout",
"version": "dev-master",
"name": "checkout/checkout-sdk-php",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/beganovich/omnipay-checkout.git",
"reference": "a4e78bc3ce6ea39ea2c2b7da3019b3966fc86a21"
"url": "https://github.com/checkout/checkout-sdk-php.git",
"reference": "c83ecc54e549efde8ac53cf1bc9701e800d98b0b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/beganovich/omnipay-checkout/zipball/a4e78bc3ce6ea39ea2c2b7da3019b3966fc86a21",
"reference": "a4e78bc3ce6ea39ea2c2b7da3019b3966fc86a21",
"url": "https://api.github.com/repos/checkout/checkout-sdk-php/zipball/c83ecc54e549efde8ac53cf1bc9701e800d98b0b",
"reference": "c83ecc54e549efde8ac53cf1bc9701e800d98b0b",
"shasum": ""
},
"require": {
"omnipay/common": "^3",
"php": "^7.1"
"php": ">=5.4.0"
},
"require-dev": {
"omnipay/tests": "^3"
"phpunit/phpunit": "^6"
},
"type": "library",
"autoload": {
"psr-4": {
"Omnipay\\Checkout\\": "src"
"Checkout\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@ -223,18 +222,28 @@
],
"authors": [
{
"name": "Benjamin Beganović",
"email": "ben@invoiceninja.com",
"role": "Developer"
"name": "Checkout.com",
"email": "platforms@checkout.com",
"homepage": "https://github.com/checkout/checkout-sdk-php/graphs/contributors"
}
],
"description": "Checkout driver for the Omnipay PHP payment processing library",
"homepage": "https://github.com/beganovich/omnipay-checkout",
"description": "Checkout.com SDK for PHP",
"homepage": "https://github.com/checkout/checkout-sdk-php",
"keywords": [
"beganovich",
"omnipay-checkout"
"CKO",
"GW3",
"Reboot",
"api",
"checkout",
"checkout.com",
"checkoutcom",
"gateway",
"library",
"payment",
"php",
"sdk"
],
"time": "2020-05-11T22:18:27+00:00"
"time": "2019-07-05T16:22:08+00:00"
},
{
"name": "cleverit/ubl_invoice",
@ -8697,6 +8706,52 @@
],
"time": "2020-05-05T10:53:32+00:00"
},
{
"name": "beganovich/omnipay-checkout",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/beganovich/omnipay-checkout.git",
"reference": "a4e78bc3ce6ea39ea2c2b7da3019b3966fc86a21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/beganovich/omnipay-checkout/zipball/a4e78bc3ce6ea39ea2c2b7da3019b3966fc86a21",
"reference": "a4e78bc3ce6ea39ea2c2b7da3019b3966fc86a21",
"shasum": ""
},
"require": {
"omnipay/common": "^3",
"php": "^7.1"
},
"require-dev": {
"omnipay/tests": "^3"
},
"type": "library",
"autoload": {
"psr-4": {
"Omnipay\\Checkout\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Benjamin Beganović",
"email": "ben@invoiceninja.com",
"role": "Developer"
}
],
"description": "Checkout driver for the Omnipay PHP payment processing library",
"homepage": "https://github.com/beganovich/omnipay-checkout",
"keywords": [
"beganovich",
"omnipay-checkout"
],
"time": "2020-05-11T22:18:27+00:00"
},
{
"name": "beyondcode/laravel-dump-server",
"version": "1.3.0",
@ -11049,7 +11104,6 @@
"aliases": [],
"minimum-stability": "dev",
"stability-flags": {
"beganovich/omnipay-checkout": 20,
"webpatser/laravel-countries": 20
},
"prefer-stable": true,

View File

@ -302,18 +302,18 @@ class RandomDataSeeder extends Seeder
// $cg->save();
// }
// if(config('ninja.testvars.checkout')) {
// $cg = new CompanyGateway;
// $cg->company_id = $company->id;
// $cg->user_id = $user->id;
// $cg->gateway_key = '3758e7f7c6f4cecf0f4f348b9a00f456';
// $cg->require_cvv = true;
// $cg->show_billing_address = true;
// $cg->show_shipping_address = true;
// $cg->update_details = true;
// $cg->config = encrypt(config('ninja.testvars.checkout'));
// $cg->save();
// }
if(config('ninja.testvars.checkout')) {
$cg = new CompanyGateway;
$cg->company_id = $company->id;
$cg->user_id = $user->id;
$cg->gateway_key = '3758e7f7c6f4cecf0f4f348b9a00f456';
$cg->require_cvv = true;
$cg->show_billing_address = true;
$cg->show_shipping_address = true;
$cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.checkout'));
$cg->save();
}
if(config('ninja.testvars.authorize')) {
$cg = new CompanyGateway;

3
public/css/app.css vendored

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,2 @@
/*! For license information please see action-selectors.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=3)}({3:function(e,t,n){e.exports=n("Boob")},Boob:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(new(function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.parentElement=document.querySelector(".form-check-parent"),this.parentForm=document.getElementById("bulkActions")}var t,r,o;return t=e,(r=[{key:"watchCheckboxes",value:function(e){var t=this;document.querySelectorAll(".form-check-child").forEach((function(n){e.checked?(n.checked=e.checked,t.processChildItem(n,document.getElementById("bulkActions"))):(n.checked=!1,document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})))}))}},{key:"processChildItem",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};n.hasOwnProperty("single")&&document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()}));var r=document.createElement("INPUT");r.setAttribute("name","invoices[]"),r.setAttribute("value",e.dataset.value),r.setAttribute("class","child-hidden-input"),r.hidden=!0,t.append(r)}},{key:"handle",value:function(){var e=this;this.parentElement.addEventListener("click",(function(){e.watchCheckboxes(e.parentElement)}));var t=!0,n=!1,r=void 0;try{for(var o,c=function(){var t=o.value;t.addEventListener("click",(function(){e.processChildItem(t,e.parentForm)}))},u=document.querySelectorAll(".form-check-child")[Symbol.iterator]();!(t=(o=u.next()).done);t=!0)c()}catch(e){n=!0,r=e}finally{try{t||null==u.return||u.return()}finally{if(n)throw r}}}}])&&n(t.prototype,r),o&&n(t,o),e}())).handle()}});
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=4)}({4:function(e,t,n){e.exports=n("Boob")},Boob:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(new(function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.parentElement=document.querySelector(".form-check-parent"),this.parentForm=document.getElementById("bulkActions")}var t,r,o;return t=e,(r=[{key:"watchCheckboxes",value:function(e){var t=this;document.querySelectorAll(".form-check-child").forEach((function(n){e.checked?(n.checked=e.checked,t.processChildItem(n,document.getElementById("bulkActions"))):(n.checked=!1,document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})))}))}},{key:"processChildItem",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};n.hasOwnProperty("single")&&document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()}));var r=document.createElement("INPUT");r.setAttribute("name","invoices[]"),r.setAttribute("value",e.dataset.value),r.setAttribute("class","child-hidden-input"),r.hidden=!0,t.append(r)}},{key:"handle",value:function(){var e=this;this.parentElement.addEventListener("click",(function(){e.watchCheckboxes(e.parentElement)}));var t=!0,n=!1,r=void 0;try{for(var o,c=function(){var t=o.value;t.addEventListener("click",(function(){e.processChildItem(t,e.parentForm)}))},u=document.querySelectorAll(".form-check-child")[Symbol.iterator]();!(t=(o=u.next()).done);t=!0)c()}catch(e){n=!0,r=e}finally{try{t||null==u.return||u.return()}finally{if(n)throw r}}}}])&&n(t.prototype,r),o&&n(t,o),e}())).handle()}});

View File

@ -1,4 +1,2 @@
/*! For license information please see payment.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=4)}({4:function(e,t,n){e.exports=n("FuOr")},FuOr:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var r=function(){function e(t,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.shouldDisplayTerms=t,this.shouldDisplaySignature=n,this.termsAccepted=!1}var t,r,i;return t=e,(r=[{key:"handleMethodSelect",value:function(e){var t=this;document.getElementById("company_gateway_id").value=e.dataset.companyGatewayId,document.getElementById("payment_method_id").value=e.dataset.gatewayTypeId,this.shouldDisplaySignature&&!this.shouldDisplayTerms&&(this.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){t.termsAccepted=!0,t.submitForm()}))),!this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.submitForm()}))),this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){t.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.termsAccepted=!0,t.submitForm()}))}))),this.shouldDisplaySignature||this.shouldDisplayTerms||this.submitForm()}},{key:"submitForm",value:function(){document.getElementById("payment-form").submit()}},{key:"displayTerms",value:function(){document.getElementById("displayTermsModal").removeAttribute("style")}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style");var e=new SignaturePad(document.getElementById("signature-pad"),{penColor:"rgb(0, 0, 0)"});this.signaturePad=e}},{key:"handle",value:function(){var e=this;document.querySelectorAll(".dropdown-gateway-button").forEach((function(t){t.addEventListener("click",(function(){return e.handleMethodSelect(t)}))}))}}])&&n(t.prototype,r),i&&n(t,i),e}(),i=document.querySelector('meta[name="require-invoice-signature"]').content,u=document.querySelector('meta[name="show-invoice-terms"]').content;new r(Boolean(+i),Boolean(+u)).handle()}});
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=5)}({5:function(e,t,n){e.exports=n("FuOr")},FuOr:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var r=function(){function e(t,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.shouldDisplayTerms=t,this.shouldDisplaySignature=n,this.termsAccepted=!1}var t,r,i;return t=e,(r=[{key:"handleMethodSelect",value:function(e){var t=this;document.getElementById("company_gateway_id").value=e.dataset.companyGatewayId,document.getElementById("payment_method_id").value=e.dataset.gatewayTypeId,this.shouldDisplaySignature&&!this.shouldDisplayTerms&&(this.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){t.termsAccepted=!0,t.submitForm()}))),!this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.submitForm()}))),this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){t.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.termsAccepted=!0,t.submitForm()}))}))),this.shouldDisplaySignature||this.shouldDisplayTerms||this.submitForm()}},{key:"submitForm",value:function(){document.getElementById("payment-form").submit()}},{key:"displayTerms",value:function(){document.getElementById("displayTermsModal").removeAttribute("style")}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style");var e=new SignaturePad(document.getElementById("signature-pad"),{penColor:"rgb(0, 0, 0)"});this.signaturePad=e}},{key:"handle",value:function(){var e=this;document.querySelectorAll(".dropdown-gateway-button").forEach((function(t){t.addEventListener("click",(function(){return e.handleMethodSelect(t)}))}))}}])&&n(t.prototype,r),i&&n(t,i),e}(),i=document.querySelector('meta[name="require-invoice-signature"]').content,u=document.querySelector('meta[name="show-invoice-terms"]').content;new r(Boolean(+i),Boolean(+u)).handle()}});

View File

@ -0,0 +1,2 @@
/*! For license information please see checkout.com.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=8)}({8:function(e,t,n){e.exports=n("XYrq")},XYrq:function(e,t){window.CKOConfig={publicKey:document.querySelector('meta[name="public-key"]').content,customerEmail:document.querySelector('meta[name="customer-email"]').content,value:document.querySelector('meta[name="value"]').content,currency:document.querySelector('meta[name="currency"]').content,paymentMode:"cards",cardFormMode:"cardTokenisation",cardTokenised:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.data),document.querySelector('input[name="store_card"]').value=document.getElementById("store-card-checkbox").checked?1:0,document.getElementById("server-response").submit()}}}});

View File

@ -0,0 +1,9 @@
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/

View File

@ -1,3 +1,2 @@
/*! For license information please see process.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=7)}({7:function(e,t,n){e.exports=n("OXGg")},OXGg:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}new(function(){function e(t,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.key=t,this.usingToken=n}var t,r,o;return t=e,(r=[{key:"setupStripe",value:function(){return this.stripe=Stripe(this.key),this.elements=this.stripe.elements(),this}},{key:"createElement",value:function(){return this.cardElement=this.elements.create("card"),this}},{key:"mountCardElement",value:function(){return this.cardElement.mount("#card-element"),this}},{key:"completePaymentUsingToken",value:function(){var e=this,t=document.getElementById("pay-now-with-token");this.stripe.handleCardPayment(t.dataset.secret,{payment_method:t.dataset.token}).then((function(t){return t.error?e.handleFailure(t.error.message):e.handleSuccess(t)}))}},{key:"completePaymentWithoutToken",value:function(){var e=this,t=document.getElementById("pay-now"),n=document.getElementById("cardholder-name");this.stripe.handleCardPayment(t.dataset.secret,this.cardElement,{payment_method_data:{billing_details:{name:n.value}}}).then((function(t){return t.error?e.handleFailure(t.error.message):e.handleSuccess(t)}))}},{key:"handleSuccess",value:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.paymentIntent);var t=document.querySelector('input[name="token-billing-checkbox"]');t&&(document.querySelector('input[name="store_card"]').value=t.checked),document.getElementById("server-response").submit()}},{key:"handleFailure",value:function(e){var t=document.getElementById("errors");t.textContent="",t.textContent=e,t.hidden=!1}},{key:"handle",value:function(){var e=this;this.setupStripe(),this.usingToken&&document.getElementById("pay-now-with-token").addEventListener("click",(function(){return e.completePaymentUsingToken()})),this.usingToken||(this.createElement().mountCardElement(),document.getElementById("pay-now").addEventListener("click",(function(){return e.completePaymentWithoutToken()})))}}])&&n(t.prototype,r),o&&n(t,o),e}())(document.querySelector('meta[name="stripe-publishable-key"]').content,document.querySelector('meta[name="using-token"]').content).handle()}});
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=11)}({11:function(e,t,n){e.exports=n("OXGg")},OXGg:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}new(function(){function e(t,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.key=t,this.usingToken=n}var t,r,o;return t=e,(r=[{key:"setupStripe",value:function(){return this.stripe=Stripe(this.key),this.elements=this.stripe.elements(),this}},{key:"createElement",value:function(){return this.cardElement=this.elements.create("card"),this}},{key:"mountCardElement",value:function(){return this.cardElement.mount("#card-element"),this}},{key:"completePaymentUsingToken",value:function(){var e=this,t=document.getElementById("pay-now-with-token");this.stripe.handleCardPayment(t.dataset.secret,{payment_method:t.dataset.token}).then((function(t){return t.error?e.handleFailure(t.error.message):e.handleSuccess(t)}))}},{key:"completePaymentWithoutToken",value:function(){var e=this,t=document.getElementById("pay-now"),n=document.getElementById("cardholder-name");this.stripe.handleCardPayment(t.dataset.secret,this.cardElement,{payment_method_data:{billing_details:{name:n.value}}}).then((function(t){return t.error?e.handleFailure(t.error.message):e.handleSuccess(t)}))}},{key:"handleSuccess",value:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.paymentIntent);var t=document.querySelector('input[name="token-billing-checkbox"]');t&&(document.querySelector('input[name="store_card"]').value=t.checked),document.getElementById("server-response").submit()}},{key:"handleFailure",value:function(e){var t=document.getElementById("errors");t.textContent="",t.textContent=e,t.hidden=!1}},{key:"handle",value:function(){var e=this;this.setupStripe(),this.usingToken&&document.getElementById("pay-now-with-token").addEventListener("click",(function(){return e.completePaymentUsingToken()})),this.usingToken||(this.createElement().mountCardElement(),document.getElementById("pay-now").addEventListener("click",(function(){return e.completePaymentWithoutToken()})))}}])&&n(t.prototype,r),o&&n(t,o),e}())(document.querySelector('meta[name="stripe-publishable-key"]').content,document.querySelector('meta[name="using-token"]').content).handle()}});

View File

@ -1,3 +1,3 @@
/*! For license information please see action-selectors.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=5)}({5:function(e,t,n){e.exports=n("ydWM")},ydWM:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(new(function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.parentElement=document.querySelector(".form-check-parent"),this.parentForm=document.getElementById("bulkActions")}var t,r,o;return t=e,(r=[{key:"watchCheckboxes",value:function(e){var t=this;document.querySelectorAll(".form-check-child").forEach((function(n){e.checked?(n.checked=e.checked,t.processChildItem(n,document.getElementById("bulkActions"))):(n.checked=!1,document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})))}))}},{key:"processChildItem",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};n.hasOwnProperty("single")&&document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()}));var r=document.createElement("INPUT");r.setAttribute("name","quotes[]"),r.setAttribute("value",e.dataset.value),r.setAttribute("class","child-hidden-input"),r.hidden=!0,t.append(r)}},{key:"handle",value:function(){var e=this;this.parentElement.addEventListener("click",(function(){e.watchCheckboxes(e.parentElement)}));var t=!0,n=!1,r=void 0;try{for(var o,c=function(){var t=o.value;t.addEventListener("click",(function(){e.processChildItem(t,e.parentForm)}))},u=document.querySelectorAll(".form-check-child")[Symbol.iterator]();!(t=(o=u.next()).done);t=!0)c()}catch(e){n=!0,r=e}finally{try{t||null==u.return||u.return()}finally{if(n)throw r}}}}])&&n(t.prototype,r),o&&n(t,o),e}())).handle()}});
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=9)}({9:function(e,t,n){e.exports=n("ydWM")},ydWM:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(new(function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.parentElement=document.querySelector(".form-check-parent"),this.parentForm=document.getElementById("bulkActions")}var t,r,o;return t=e,(r=[{key:"watchCheckboxes",value:function(e){var t=this;document.querySelectorAll(".form-check-child").forEach((function(n){e.checked?(n.checked=e.checked,t.processChildItem(n,document.getElementById("bulkActions"))):(n.checked=!1,document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})))}))}},{key:"processChildItem",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};n.hasOwnProperty("single")&&document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()}));var r=document.createElement("INPUT");r.setAttribute("name","quotes[]"),r.setAttribute("value",e.dataset.value),r.setAttribute("class","child-hidden-input"),r.hidden=!0,t.append(r)}},{key:"handle",value:function(){var e=this;this.parentElement.addEventListener("click",(function(){e.watchCheckboxes(e.parentElement)}));var t=!0,n=!1,r=void 0;try{for(var o,c=function(){var t=o.value;t.addEventListener("click",(function(){e.processChildItem(t,e.parentForm)}))},u=document.querySelectorAll(".form-check-child")[Symbol.iterator]();!(t=(o=u.next()).done);t=!0)c()}catch(e){n=!0,r=e}finally{try{t||null==u.return||u.return()}finally{if(n)throw r}}}}])&&n(t.prototype,r),o&&n(t,o),e}())).handle()}});

View File

@ -1,3 +1,3 @@
/*! For license information please see approve.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}({6:function(e,t,n){e.exports=n("WuMn")},WuMn:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var r=function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.shouldDisplaySignature=t}var t,r,o;return t=e,(r=[{key:"submitForm",value:function(){document.getElementById("approve-form").submit()}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style"),new SignaturePad(document.getElementById("signature-pad"),{backgroundColor:"rgb(240,240,240)",penColor:"rgb(0, 0, 0)"})}},{key:"handle",value:function(){var e=this;document.getElementById("approve-button").addEventListener("click",(function(){e.shouldDisplaySignature&&(e.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){e.submitForm()}))),e.shouldDisplaySignature||e.submitForm()}))}}])&&n(t.prototype,r),o&&n(t,o),e}(),o=document.querySelector('meta[name="require-quote-signature"]').content;new r(Boolean(+o)).handle()}});
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=10)}({10:function(e,t,n){e.exports=n("WuMn")},WuMn:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var r=function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.shouldDisplaySignature=t}var t,r,o;return t=e,(r=[{key:"submitForm",value:function(){document.getElementById("approve-form").submit()}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style"),new SignaturePad(document.getElementById("signature-pad"),{backgroundColor:"rgb(240,240,240)",penColor:"rgb(0, 0, 0)"})}},{key:"handle",value:function(){var e=this;document.getElementById("approve-button").addEventListener("click",(function(){e.shouldDisplaySignature&&(e.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){e.submitForm()}))),e.shouldDisplaySignature||e.submitForm()}))}}])&&n(t.prototype,r),o&&n(t,o),e}(),o=document.querySelector('meta[name="require-quote-signature"]').content;new r(Boolean(+o)).handle()}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,14 +1,17 @@
{
"/js/app.js": "/js/app.js?id=8b49701583f407403ddf",
"/css/app.css": "/css/app.css?id=9082c02ea8f150e2a3e9",
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=725ed8b1ad1518cdffe9",
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=af22ef81288656e46b7f",
"/css/app.css": "/css/app.css?id=05d9dbe4a834b13c2fde",
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=d16c0e6728b00d329cbb",
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
"/js/clients/payment_methods/authorize-ach.js": "/js/clients/payment_methods/authorize-ach.js?id=30a5db56b004becf4715",
"/js/clients/payment_methods/authorize-authorize-card.js": "/js/clients/payment_methods/authorize-authorize-card.js?id=b0a1bd21a57e12cd491a",
"/js/clients/payment_methods/authorize-stripe-card.js": "/js/clients/payment_methods/authorize-stripe-card.js?id=f4c45f0da9868d840799",
"/js/clients/payments/process.js": "/js/clients/payments/process.js?id=a97ddadb7af0563c1d4b",
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=3af82eeaf86fe5efaa2c",
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=972c7cc8e9d9406babfa",
"/js/clients/shared/pdf.js": "/js/clients/shared/pdf.js?id=afc25cff1d17c538d66d",
"/js/setup/setup.js": "/js/setup/setup.js?id=39f1625d7fbbda12d0e3"
"/js/clients/payments/alipay.js": "/js/clients/payments/alipay.js?id=04778cbf46488e8f6b5f",
"/js/clients/payments/checkout.com.js": "/js/clients/payments/checkout.com.js?id=591618c8bcd926b7111d",
"/js/clients/payments/process.js": "/js/clients/payments/process.js?id=be2b10b1b5e3a727f6e2",
"/js/clients/payments/sofort.js": "/js/clients/payments/sofort.js?id=f9253aea74535bc46886",
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=88ff76c9ca1c15fc011b",
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=9cdbe50bab63dc1dd520",
"/js/clients/shared/pdf.js": "/js/clients/shared/pdf.js?id=5df2af6e8ba88b2621d9",
"/js/setup/setup.js": "/js/setup/setup.js?id=cd5d37e5eddb88678da4"
}

View File

@ -0,0 +1,30 @@
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
window.CKOConfig = {
publicKey: document.querySelector('meta[name="public-key"]').content,
customerEmail: document.querySelector('meta[name="customer-email"]')
.content,
value: document.querySelector('meta[name="value"]').content,
currency: document.querySelector('meta[name="currency"]').content,
paymentMode: 'cards',
cardFormMode: 'cardTokenisation',
cardTokenised: function(event) {
document.querySelector(
'input[name="gateway_response"]'
).value = JSON.stringify(event.data);
document.querySelector(
'input[name="store_card"]'
).value = document.getElementById('store-card-checkbox').checked ? 1 : 0;
document.getElementById('server-response').submit();
},
};

View File

@ -3211,4 +3211,8 @@ return [
'verification' => 'Verification',
'complete_your_bank_account_verification' => 'Before using bank account they must be verified.',
'checkout_com' => 'Checkout.com',
'footer_label' => 'Copyright © :year Invoice Ninja. All rights reserved.',
];

View File

@ -0,0 +1,8 @@
<footer class="bg-white px-4 py-5 shadow px-4 sm:px-6 md:px-8 flex justify-center border border-gray-200 justify-between items-center">
<span class="text-sm text-gray-700">{{ ctrans('texts.footer_label', ['year' => date('Y')]) }}</span>
@if(!auth()->user()->user->account->isPaid())
<a href="#">
<img class="h-8" src="{{ asset('images/invoiceninja-black-logo-2.png') }}" alt="Invoice Ninja Logo">
</a>
@endif
</footer>

View File

@ -1,23 +1,44 @@
<div class="hidden md:flex md:flex-shrink-0">
<div class="flex flex-col w-64">
<div class="flex items-center h-16 flex-shrink-0 px-4 bg-blue-900">
<div class="flex items-center h-16 flex-shrink-0 px-4 bg-blue-900 justify-center">
<a href="{{ route('client.dashboard') }}">
<img class="h-6 w-auto"
src="{!! $settings->company_logo ?: asset('images/invoiceninja-white-logo.png') !!}"
alt="{{ config('app.name') }}"/>
<img class="h-8 w-auto" src="{!! $settings->company_logo ?: asset('images/invoiceninja-white-logo.png') !!}" alt="{{ config('app.name') }}" />
</a>
</div>
<div class="h-0 flex-1 flex flex-col overflow-y-auto">
<nav class="flex-1 py-4 bg-blue-800">
@foreach($sidebar as $row)
<a class="group flex items-center p-4 text-sm leading-5 font-medium text-white bg-blue-800 hover:bg-blue-900 focus:outline-none focus:bg-blue-900 transition ease-in-out duration-150 {{ isActive($row['url']) }}"
href="{{ route($row['url']) }}">
<a class="group flex items-center p-4 text-sm leading-5 font-medium text-white bg-blue-800 hover:bg-blue-900 focus:outline-none focus:bg-blue-900 transition ease-in-out duration-150 {{ isActive($row['url']) }}" href="{{ route($row['url']) }}">
<img src="{{ asset('images/svg/' . $row['icon'] . '.svg') }}" class="w-5 h-5 fill-current text-white mr-3" alt="" />
{{ $row['title'] }}
</a>
@endforeach
</nav>
<div class="flex-shrink-0 flex bg-blue-800 p-4 justify-center">
<div class="flex items-center">
<a href="https://www.facebook.com/invoiceninja/">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path>
</svg>
</a>
<a href="https://twitter.com/invoiceninja">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path>
</svg>
</a>
<a href="https://github.com/invoiceninja/invoiceninja">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg> </a>
<a href="https://www.invoiceninja.com/contact">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
</a>
</div>
</div>
</div>
<div class="flex-shrink-0 w-14"></div>
</div>
</div>

View File

@ -4,21 +4,9 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h7" />
</svg>
</button>
<div class="flex-1 px-4 flex justify-between">
<div class="flex-1 flex">
<div class="w-full flex md:ml-0">
<label for="search_field" class="sr-only">{{ ctrans('texts.search') }}</label>
<div class="relative w-full text-gray-400 focus-within:text-gray-600">
<div class="absolute inset-y-0 left-0 flex items-center pointer-events-none">
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" />
</svg>
</div>
<input id="search_field" class="block w-full h-full pl-8 pr-3 py-2 rounded-md text-gray-900 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 sm:text-sm" placeholder="Search" />
</div>
</div>
</div>
<div class="ml-4 flex items-center md:ml-6">
<div class="flex-1 px-3 md:px-8 flex justify-between items-center">
<span class="text-xl text-gray-900">@yield('meta_title')</span>
<div class="flex items-center md:ml-6 md:mr-2">
@if($multiple_contacts->count() > 1)
<div class="relative inline-block text-left" x-data="{ open: false }">
<div>

View File

@ -1,7 +1,8 @@
<div
class="h-screen flex overflow-hidden bg-gray-100"
x-data="{ sidebarOpen: false }"
@keydown.window.escape="sidebarOpen = false">
@keydown.window.escape="sidebarOpen = false"
id="main-sidebar">
<!-- Off-canvas menu for mobile -->
@include('portal.ninja2020.components.general.sidebar.mobile')
@ -12,7 +13,7 @@
<div class="flex flex-col w-0 flex-1 overflow-hidden">
@include('portal.ninja2020.components.general.sidebar.header')
<main
class="flex-1 relative z-0 overflow-y-auto py-6 focus:outline-none"
class="flex-1 relative z-0 overflow-y-auto pt-6 focus:outline-none"
tabindex="0" x-data
x-init="$el.focus()">
@ -21,11 +22,16 @@
</div>
<div class="mx-auto px-4 sm:px-6 md:px-8">
<div class="py-4">
<div class="pt-4">
@includeWhen(session()->has('success'), 'portal.ninja2020.components.general.messages.success')
{{ $slot }}
</div>
</div>
</main>
@include('portal.ninja2020.components.general.footer')
</div>
</div>
<script>
</script>

View File

@ -1,34 +1,50 @@
<div class="md:hidden">
<div @click="sidebarOpen = false"
class="fixed inset-0 z-30 bg-gray-600 opacity-0 pointer-events-none transition-opacity ease-linear duration-300"
:class="{'opacity-75 pointer-events-auto': sidebarOpen, 'opacity-0 pointer-events-none': !sidebarOpen}"></div>
<div
class="fixed inset-y-0 left-0 flex flex-col z-40 max-w-xs w-full pt-5 pb-4 bg-blue-800 transform ease-in-out duration-300 -translate-x-full"
:class="{'translate-x-0': sidebarOpen, '-translate-x-full': !sidebarOpen}">
<div @click="sidebarOpen = false" class="fixed inset-0 z-30 bg-gray-600 opacity-0 pointer-events-none transition-opacity ease-linear duration-300" :class="{'opacity-75 pointer-events-auto': sidebarOpen, 'opacity-0 pointer-events-none': !sidebarOpen}"></div>
<div class="fixed inset-y-0 left-0 flex flex-col z-40 max-w-xs w-full pt-5 pb-4 bg-blue-800 transform ease-in-out duration-300 -translate-x-full" :class="{'translate-x-0': sidebarOpen, '-translate-x-full': !sidebarOpen}">
<div class="absolute top-0 right-0 -mr-14 p-1">
<button x-show="sidebarOpen" @click="sidebarOpen = false"
class="flex items-center justify-center h-12 w-12 rounded-full focus:outline-none focus:bg-gray-600">
<button x-show="sidebarOpen" @click="sidebarOpen = false" class="flex items-center justify-center h-12 w-12 rounded-full focus:outline-none focus:bg-gray-600">
<svg class="h-6 w-6 text-white" stroke="currentColor" fill="none" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="flex-shrink-0 flex items-center px-4">
<img class="h-6 w-auto"
src="{!! $settings->company_logo ?: asset('images/invoiceninja-white-logo.png') !!}"
alt="{{ config('app.name') }}"/>
<img class="h-6 w-auto" src="{!! $settings->company_logo ?: asset('images/invoiceninja-white-logo.png') !!}" alt="{{ config('app.name') }}" />
</div>
<div class="mt-5 flex-1 h-0 overflow-y-auto">
<nav class="flex-1 py-4 bg-blue-800">
@foreach($sidebar as $row)
<a class="group flex items-center p-4 text-sm leading-5 font-medium text-white bg-blue-800 hover:bg-blue-900 focus:outline-none focus:bg-blue-900 transition ease-in-out duration-150 {{ isActive($row['url']) }}"
href="{{ route($row['url']) }}">
<img src="{{ asset('images/svg/' . $row['icon'] . '.svg') }}"
class="w-5 h-5 fill-current text-white mr-3" alt=""/>
<a class="group flex items-center p-4 text-sm leading-5 font-medium text-white bg-blue-800 hover:bg-blue-900 focus:outline-none focus:bg-blue-900 transition ease-in-out duration-150 {{ isActive($row['url']) }}" href="{{ route($row['url']) }}">
<img src="{{ asset('images/svg/' . $row['icon'] . '.svg') }}" class="w-5 h-5 fill-current text-white mr-3" alt="" />
{{ $row['title'] }}
</a>
@endforeach
</nav>
<div class="flex-shrink-0 flex bg-blue-800 p-4 justify-center">
<div class="flex items-center">
<a href="https://www.facebook.com/invoiceninja/">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path>
</svg>
</a>
<a href="https://twitter.com/invoiceninja">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path>
</svg>
</a>
<a href="https://github.com/invoiceninja/invoiceninja">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg> </a>
<a href="https://www.invoiceninja.com/contact">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
</a>
</div>
</div>
</div>
<div class="flex-shrink-0 w-14"></div>
</div>
</div>

View File

@ -9,6 +9,9 @@
<option>20</option>
</select>
</div>
@if($client->getCreditCardGateway())
<a href="{{ route('client.payment_methods.create') }}" class="button button-primary">{{ ctrans('texts.add_payment_method') }}</a>
@endif
</div>
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
<div class="align-middle inline-block min-w-full overflow-hidden rounded">

View File

@ -9,27 +9,10 @@
@endforeach
</div>
@endif
<div class="bg-white shadow rounded mb-4" translate>
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.credits') }}
</h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p translate>
{{ ctrans('texts.list_of_credits') }}
</p>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('body')
<div class="flex flex-col mt-4">
<div class="flex flex-col">
@livewire('credits-table')
</div>
@endsection

View File

@ -9,27 +9,8 @@
->message($client->getSetting('custom_message_dashboard')) !!}
@endcomponent
@endif
<div class="bg-white shadow rounded mb-4">
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.dashboard') }}
</h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p>
{{ ctrans('texts.quick_overview_statistics') }}
</p>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('body')
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet esse magnam nam numquam omnis optio, pariatur
perferendis quae quaerat quam, quas quos repellat sapiente sit soluta, tenetur totam ut vel veritatis voluptatibus?
Aut, dolor illo? Asperiores eum eveniet quae sed?
This page is empty, sad and alone.
@endsection

View File

@ -1,42 +1,97 @@
@extends('portal.ninja2020.layout.app')
@section('meta_title', ctrans('texts.checkout_com'))
<script src="https://cdn.checkout.com/sandbox/js/checkout.js"></script>
<form class="payment-form" method="POST" action="https://merchant.com/successUrl">
<script>
Checkout.render({
publicKey: 'pk_test_6ff46046-30af-41d9-bf58-929022d2cd14',
paymentToken: 'pay_tok_SPECIMEN-000',
customerEmail: 'user@email.com',
value: 100,
currency: 'GBP',
cardFormMode: 'cardTokenisation',
cardTokenised: function(event) {
console.log(event.data.cardToken);
}
});
</script>
@push('head')
<meta name="public-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="customer-email" content="{{ $customer_email }}">
<meta name="value" content="{{ $value }}">
<meta name="currency" content="{{ $currency }}">
<script src="{{ asset('js/clients/payments/checkout.com.js') }}"></script>
@endpush
@section('body')
<form action="{{ route('client.payments.response') }}" method="post" id="server-response">
@csrf
<input type="hidden" name="gateway_response">
<input type="hidden" name="store_card">
@foreach($invoices as $invoice)
<input type="hidden" name="hashed_ids[]" value="{{ $invoice->hashed_id }}">
@endforeach
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
<input type="hidden" name="value" value="{{ $value }}">
<input type="hidden" name="raw_value" value="{{ $raw_value }}">
<input type="hidden" name="currency" value="{{ $currency }}">
@isset($token)
<input type="hidden" name="token" value="{{ $token->meta->id }}">
@endisset
</form>
<!--
Checkout.render({
debugMode: {{ $gateway->getConfigField('testMode') ? 'true' : 'false' }},
publicKey: '{{ $gateway->getConfigField('publicApiKey') }}',
paymentToken: '{{ $token }}',
customerEmail: '{{ $contact->email }}',
customerName: '{{ $contact->getFullName() }}',
@if( $invoice->getCurrencyCode() == 'BHD' || $invoice->getCurrencyCode() == 'KWD' || $invoice->getCurrencyCode() == 'OMR')
value: {{ $invoice->getRequestedAmount() * 1000 }},
<div class="container mx-auto">
<div class="grid grid-cols-6 gap-4">
<div class="col-span-6 md:col-start-2 md:col-span-4">
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.pay_now') }}
</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
{{ ctrans('texts.complete_your_payment') }}
</p>
</div>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.payment_type') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ ctrans('texts.checkout_com') }} ({{ ctrans('texts.credit_card') }})
</dd>
</div>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.amount') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<span class="font-bold">{{ App\Utils\Number::formatMoney($amount, $client) }}</span>
</dd>
</div>
@isset($token)
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.card_number') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
**** {{ ucfirst($token->meta->last4) }}
</dd>
</div>
<div class="bg-white px-4 py-5 flex justify-end">
<button class="button button-primary" onclick="document.getElementById('server-response').submit()">
{{ ctrans('texts.pay_now') }}
</button>
</div>
@else
value: {{ $invoice->getRequestedAmount() * 100 }},
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.token_billing_checkbox') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<input type="checkbox" id="store-card-checkbox" class="form-checkbox">
</dd>
</div>
<div class="bg-white px-4 py-5 flex justify-end">
<form class="payment-form" method="POST" action="https://merchant.com/successUrl">
@if(app()->environment() == 'production')
<script async src="https://cdn.checkout.com/js/checkout.js"></script>
@else
<script async src="https://cdn.checkout.com/sandbox/js/checkout.js"></script>
@endif
currency: '{{ $invoice->getCurrencyCode() }}',
widgetContainerSelector: '.payment-form',
widgetColor: '#333',
themeColor: '#3075dd',
buttonColor:'#51c470',
cardCharged: function(event){
location.href = '{{ URL::to('/complete/'. $invitation->invitation_key . '/credit_card?token=' . $transactionToken) }}';
}
});
-->
</form>
</div>
@endisset
</div>
</div>
</div>
</div>
@endsection

View File

@ -4,7 +4,6 @@
@push('head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="using-token" content="{{ boolval($token) }}">
<meta name="turbolinks-visit-control" content="reload">
@endpush
@section('body')
@ -27,7 +26,7 @@
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.pay_now') }}
</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500" translate>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
{{ ctrans('texts.complete_your_payment') }}
</p>
</div>

View File

@ -2,7 +2,6 @@
@section('meta_title', ctrans('texts.invoices'))
@section('header')
@if($errors->any())
<div class="alert alert-failure mb-4">
@foreach($errors->all() as $error)
@ -10,28 +9,10 @@
@endforeach
</div>
@endif
<div class="bg-white shadow rounded mb-4">
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.invoices') }}
</h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p>
{{ ctrans('texts.list_of_invoices') }}
</p>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('body')
<div class="flex justify-end items-center">
<span class="text-sm mr-2">{{ ctrans('texts.with_selected') }}:</span>
<div class="flex items-center">
<form action="{{ route('client.invoices.bulk') }}" method="post" id="bulkActions">
@csrf
<button type="submit" class="button button-primary" name="action" value="download">{{ ctrans('texts.download') }}</button>

View File

@ -2,29 +2,9 @@
@section('meta_title', ctrans('texts.payment_methods'))
@section('header')
<div class="bg-white shadow rounded mb-4" translate>
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.payment_methods') }}
</h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p translate>
{{ ctrans('texts.list_of_payment_methods') }}
</p>
</div>
</div>
<div class="mt-5 sm:mt-0 sm:ml-6 sm:flex-shrink-0 sm:flex sm:items-center">
<div class="inline-flex rounded-md shadow-sm">
<input type="hidden" name="hashed_ids">
<input type="hidden" name="action" value="payment">
@if($client->getCreditCardGateway())
<a href="{{ route('client.payment_methods.create') }}" class="button button-primary">@lang('texts.add_payment_method')</a>
@endif
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -27,7 +27,8 @@
{{ ctrans('texts.type') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ ucfirst($payment_method->meta->brand) }}
{{ optional($payment_method->meta)->brand }}
{{ optional($payment_method->meta)->scheme }}
</dd>
</div>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">

View File

@ -1,25 +1,6 @@
@extends('portal.ninja2020.layout.app')
@section('meta_title', ctrans('texts.payments'))
@section('header')
<div class="bg-white shadow rounded mb-4" translate>
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.payments') }}
</h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p translate>
{{ ctrans('texts.list_of_payments') }}
</p>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('body')
<div class="flex flex-col">
@livewire('payments-table')

View File

@ -35,7 +35,7 @@
{{ ctrans('texts.method') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ $payment->type->name }}
{{ optional($payment->type)->name }}
</dd>
</div>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
@ -62,7 +62,7 @@
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.invoices') }}
</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500" translate>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
{{ ctrans('texts.list_of_payment_invoices') }}
</p>
</div>

View File

@ -9,23 +9,6 @@
@endforeach
</div>
@endif
<div class="bg-white shadow rounded mb-4" translate>
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.quotes') }}
</h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p translate>
{{ ctrans('texts.list_of_quotes') }}
</p>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('body')

View File

@ -1,25 +1,6 @@
@extends('portal.ninja2020.layout.app')
@section('meta_title', ctrans('texts.recurring_invoices'))
@section('header')
<div class="bg-white shadow rounded mb-4" translate>
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.recurring_invoices') }}
</h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p>
{{ ctrans('texts.list_of_recurring_invoices') }}
</p>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('body')
<div class="flex flex-col">
@livewire('recurring-invoices-table')

4
webpack.mix.js vendored
View File

@ -30,6 +30,10 @@ mix.js("resources/js/app.js", "public/js")
"resources/js/clients/payments/alipay.js",
"public/js/clients/payments/alipay.js"
)
.js(
"resources/js/clients/payments/checkout.com.js",
"public/js/clients/payments/checkout.com.js"
)
.js(
"resources/js/clients/quotes/action-selectors.js",
"public/js/clients/quotes/action-selectors.js"