mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge branch 'develop' of github.com:invoiceninja/invoiceninja into develop
This commit is contained in:
commit
fed2e57891
@ -51,6 +51,7 @@ class ProjectController extends BaseController
|
|||||||
public function create(ProjectRequest $request)
|
public function create(ProjectRequest $request)
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
|
'account' => auth()->user()->account,
|
||||||
'project' => null,
|
'project' => null,
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
'url' => 'projects',
|
'url' => 'projects',
|
||||||
@ -67,6 +68,7 @@ class ProjectController extends BaseController
|
|||||||
$project = $request->entity();
|
$project = $request->entity();
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
|
'account' => auth()->user()->account,
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
'method' => 'PUT',
|
'method' => 'PUT',
|
||||||
'url' => 'projects/' . $project->public_id,
|
'url' => 'projects/' . $project->public_id,
|
||||||
|
@ -11,7 +11,7 @@ class TwoFactorController extends Controller
|
|||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
if ($user->google_2fa_secret || ! $user->phone) {
|
if ($user->google_2fa_secret || ! $user->phone || ! $user->confirmed) {
|
||||||
return redirect('/settings/user_details');
|
return redirect('/settings/user_details');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ class TwoFactorController extends Controller
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$secret = session()->pull('2fa:secret');
|
$secret = session()->pull('2fa:secret');
|
||||||
|
|
||||||
if ($secret && ! $user->google_2fa_secret && $user->phone) {
|
if ($secret && ! $user->google_2fa_secret && $user->phone && $user->confirmed) {
|
||||||
$user->google_2fa_secret = Crypt::encrypt($secret);
|
$user->google_2fa_secret = Crypt::encrypt($secret);
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
|
@ -89,6 +89,11 @@ class Utils
|
|||||||
return env('NINJA_DEV') == 'true';
|
return env('NINJA_DEV') == 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function isTimeTracker()
|
||||||
|
{
|
||||||
|
return array_get($_SERVER, 'HTTP_USER_AGENT') == TIME_TRACKER_USER_AGENT;
|
||||||
|
}
|
||||||
|
|
||||||
public static function requireHTTPS()
|
public static function requireHTTPS()
|
||||||
{
|
{
|
||||||
if (Request::root() === 'http://ninja.dev' || Request::root() === 'http://ninja.dev:8000') {
|
if (Request::root() === 'http://ninja.dev' || Request::root() === 'http://ninja.dev:8000') {
|
||||||
|
@ -126,7 +126,7 @@ class Activity extends Eloquent
|
|||||||
'user' => $isSystem ? '<i>' . trans('texts.system') . '</i>' : e($user->getDisplayName()),
|
'user' => $isSystem ? '<i>' . trans('texts.system') . '</i>' : e($user->getDisplayName()),
|
||||||
'invoice' => $invoice ? link_to($invoice->getRoute(), $invoice->getDisplayName()) : null,
|
'invoice' => $invoice ? link_to($invoice->getRoute(), $invoice->getDisplayName()) : null,
|
||||||
'quote' => $invoice ? link_to($invoice->getRoute(), $invoice->getDisplayName()) : null,
|
'quote' => $invoice ? link_to($invoice->getRoute(), $invoice->getDisplayName()) : null,
|
||||||
'contact' => $contactId ? e($client->getDisplayName()) : e($user->getDisplayName()),
|
'contact' => $contactId ? link_to($client->getRoute(), $client->getDisplayName()) : e($user->getDisplayName()),
|
||||||
'payment' => $payment ? e($payment->transaction_reference) : null,
|
'payment' => $payment ? e($payment->transaction_reference) : null,
|
||||||
'payment_amount' => $payment ? $account->formatMoney($payment->amount, $payment) : null,
|
'payment_amount' => $payment ? $account->formatMoney($payment->amount, $payment) : null,
|
||||||
'adjustment' => $this->adjustment ? $account->formatMoney($this->adjustment, $this) : null,
|
'adjustment' => $this->adjustment ? $account->formatMoney($this->adjustment, $this) : null,
|
||||||
|
@ -15,8 +15,17 @@ class ActivityDatatable extends EntityDatatable
|
|||||||
'activities.id',
|
'activities.id',
|
||||||
function ($model) {
|
function ($model) {
|
||||||
$str = Utils::timestampToDateTimeString(strtotime($model->created_at));
|
$str = Utils::timestampToDateTimeString(strtotime($model->created_at));
|
||||||
|
$activityTypes = [
|
||||||
|
ACTIVITY_TYPE_VIEW_INVOICE,
|
||||||
|
ACTIVITY_TYPE_VIEW_QUOTE,
|
||||||
|
ACTIVITY_TYPE_CREATE_PAYMENT,
|
||||||
|
ACTIVITY_TYPE_APPROVE_QUOTE,
|
||||||
|
];
|
||||||
|
|
||||||
if ($model->contact_id && ! in_array($model->ip, ['127.0.0.1', '192.168.255.33'])) {
|
if ($model->contact_id
|
||||||
|
&& ! $model->is_system
|
||||||
|
&& in_array($model->activity_type_id, $activityTypes)
|
||||||
|
&& ! in_array($model->ip, ['127.0.0.1', '192.168.255.33'])) {
|
||||||
$ipLookUpLink = IP_LOOKUP_URL . $model->ip;
|
$ipLookUpLink = IP_LOOKUP_URL . $model->ip;
|
||||||
$str .= sprintf(' <i class="fa fa-globe" style="cursor:pointer" title="%s" onclick="openUrl(\'%s\', \'IP Lookup\')"></i>', $model->ip, $ipLookUpLink);
|
$str .= sprintf(' <i class="fa fa-globe" style="cursor:pointer" title="%s" onclick="openUrl(\'%s\', \'IP Lookup\')"></i>', $model->ip, $ipLookUpLink);
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,18 @@ class AccountPresenter extends Presenter
|
|||||||
return Utils::addHttp($this->entity->website);
|
return Utils::addHttp($this->entity->website);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function taskRate()
|
||||||
|
{
|
||||||
|
if ($this->entity->task_rate) {
|
||||||
|
return Utils::roundSignificant($this->entity->task_rate);
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
|
@ -50,4 +50,16 @@ class ClientPresenter extends EntityPresenter
|
|||||||
|
|
||||||
return sprintf('%s: %s %s', trans('texts.payment_terms'), trans('texts.payment_terms_net'), $client->defaultDaysDue());
|
return sprintf('%s: %s %s', trans('texts.payment_terms'), trans('texts.payment_terms_net'), $client->defaultDaysDue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function taskRate()
|
||||||
|
{
|
||||||
|
if ($this->entity->task_rate) {
|
||||||
|
return Utils::roundSignificant($this->entity->task_rate);
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2519,6 +2519,9 @@ $LANG = array(
|
|||||||
'add_product' => 'Add Product',
|
'add_product' => 'Add Product',
|
||||||
'email_will_be_sent_on' => 'Note: the email will be sent on :date.',
|
'email_will_be_sent_on' => 'Note: the email will be sent on :date.',
|
||||||
'invoice_product' => 'Invoice Product',
|
'invoice_product' => 'Invoice Product',
|
||||||
|
'self_host_login' => 'Self-Host Login',
|
||||||
|
'set_self_hoat_url' => 'Self-Host URL',
|
||||||
|
'local_storage_required' => 'Error: local storage is not available.',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
!!}
|
!!}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if ($user->confirmed)
|
||||||
@if ($user->google_2fa_secret)
|
@if ($user->google_2fa_secret)
|
||||||
{!! Former::checkbox('enable_two_factor')
|
{!! Former::checkbox('enable_two_factor')
|
||||||
->help(trans('texts.enable_two_factor_help'))
|
->help(trans('texts.enable_two_factor_help'))
|
||||||
@ -63,7 +64,7 @@
|
|||||||
{!! Former::plaintext('enable_two_factor')
|
{!! Former::plaintext('enable_two_factor')
|
||||||
->value('<span class="text-muted">' . trans('texts.set_phone_for_two_factor') . '</span>') !!}
|
->value('<span class="text-muted">' . trans('texts.set_phone_for_two_factor') . '</span>') !!}
|
||||||
@endif
|
@endif
|
||||||
|
@endif
|
||||||
|
|
||||||
{!! Former::checkbox('dark_mode')
|
{!! Former::checkbox('dark_mode')
|
||||||
->help(trans('texts.dark_mode_help'))
|
->help(trans('texts.dark_mode_help'))
|
||||||
|
@ -83,7 +83,11 @@
|
|||||||
{!! link_to('/recover_password', trans('texts.recover_password')) !!}
|
{!! link_to('/recover_password', trans('texts.recover_password')) !!}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5 col-sm-12">
|
<div class="col-md-5 col-sm-12">
|
||||||
|
@if (Utils::isTimeTracker())
|
||||||
|
{!! link_to('#', trans('texts.self_host_login'), ['onclick' => 'setSelfHostUrl()']) !!}
|
||||||
|
@else
|
||||||
{!! link_to(NINJA_WEB_URL.'/knowledgebase/', trans('texts.knowledge_base'), ['target' => '_blank']) !!}
|
{!! link_to(NINJA_WEB_URL.'/knowledgebase/', trans('texts.knowledge_base'), ['target' => '_blank']) !!}
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@ -111,8 +115,13 @@
|
|||||||
$('#email').focus();
|
$('#email').focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (array_get($_SERVER, 'HTTP_USER_AGENT') == TIME_TRACKER_USER_AGENT)
|
@if (Utils::isTimeTracker())
|
||||||
if (isStorageSupported()) {
|
if (isStorageSupported()) {
|
||||||
|
var selfHostUrl = localStorage.getItem('last:time_tracker:url');
|
||||||
|
if (selfHostUrl) {
|
||||||
|
location.href = selfHostUrl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
$('#email').change(function() {
|
$('#email').change(function() {
|
||||||
localStorage.setItem('last:time_tracker:email', $('#email').val());
|
localStorage.setItem('last:time_tracker:email', $('#email').val());
|
||||||
})
|
})
|
||||||
@ -124,6 +133,29 @@
|
|||||||
}
|
}
|
||||||
@endif
|
@endif
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@if (Utils::isTimeTracker())
|
||||||
|
function setSelfHostUrl() {
|
||||||
|
if (! isStorageSupported()) {
|
||||||
|
swal("{{ trans('texts.local_storage_required') }}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
swal({
|
||||||
|
title: "{{ trans('texts.set_self_hoat_url') }}",
|
||||||
|
input: 'text',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Save',
|
||||||
|
}).then(function (value) {
|
||||||
|
if (!value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
value = value.replace(/\/+$/, '') + '/time_tracker';
|
||||||
|
localStorage.setItem('last:time_tracker:url', value);
|
||||||
|
location.reload();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@endif
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -158,6 +158,7 @@
|
|||||||
->help(trans('texts.payment_terms_help')) !!}
|
->help(trans('texts.payment_terms_help')) !!}
|
||||||
@if ($account->isModuleEnabled(ENTITY_TASK))
|
@if ($account->isModuleEnabled(ENTITY_TASK))
|
||||||
{!! Former::text('task_rate')
|
{!! Former::text('task_rate')
|
||||||
|
->placeholder($account->present()->taskRate)
|
||||||
->help('task_rate_help') !!}
|
->help('task_rate_help') !!}
|
||||||
@endif
|
@endif
|
||||||
{!! Former::select('size_id')->addOption('','')
|
{!! Former::select('size_id')->addOption('','')
|
||||||
|
@ -536,7 +536,10 @@
|
|||||||
@if ($invoice->isClientTrashed())
|
@if ($invoice->isClientTrashed())
|
||||||
<!-- do nothing -->
|
<!-- do nothing -->
|
||||||
@elseif ($invoice->isSent() && config('ninja.lock_sent_invoices'))
|
@elseif ($invoice->isSent() && config('ninja.lock_sent_invoices'))
|
||||||
<!-- do nothing -->
|
@if (! $invoice->trashed())
|
||||||
|
{!! Button::info(trans("texts.email_{$entityType}"))->withAttributes(array('id' => 'emailButton', 'onclick' => 'onEmailClick()'))->appendIcon(Icon::create('send')) !!}
|
||||||
|
@endif
|
||||||
|
|
||||||
@else
|
@else
|
||||||
@if (!$invoice->is_deleted)
|
@if (!$invoice->is_deleted)
|
||||||
@if ($invoice->isSent())
|
@if ($invoice->isSent())
|
||||||
@ -1188,6 +1191,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var origInvoiceNumber = false;
|
var origInvoiceNumber = false;
|
||||||
|
var checkedInvoiceBalances = false;
|
||||||
|
|
||||||
function getPDFString(cb, force) {
|
function getPDFString(cb, force) {
|
||||||
@if (! $invoice->id && $account->credit_number_counter > 0)
|
@if (! $invoice->id && $account->credit_number_counter > 0)
|
||||||
var total = model.invoice().totals.rawTotal();
|
var total = model.invoice().totals.rawTotal();
|
||||||
@ -1201,13 +1206,30 @@
|
|||||||
}
|
}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
var invoice = createInvoiceModel();
|
||||||
|
var design = getDesignJavascript();
|
||||||
|
|
||||||
|
/*
|
||||||
|
@if ($invoice->exists)
|
||||||
|
if (! checkedInvoiceBalances) {
|
||||||
|
checkedInvoiceBalances = true;
|
||||||
|
var phpBalance = roundSignificant(invoice.balance);
|
||||||
|
var koBalance = roundSignificant(model.invoice().totals.rawTotal());
|
||||||
|
var jsBalance = roundSignificant(calculateAmounts(invoice).total_amount);
|
||||||
|
if (phpBalance == koBalance && koBalance == jsBalance) {
|
||||||
|
// do nothing
|
||||||
|
} else {
|
||||||
|
var invitationKey = invoice.invitations[0].invitation_key;
|
||||||
|
window.onerror(invitationKey + ': Balances do not match | PHP: ' + phpBalance + ', JS: ' + jsBalance + ', KO: ' + koBalance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endif
|
||||||
|
*/
|
||||||
|
|
||||||
@if ( ! $account->live_preview)
|
@if ( ! $account->live_preview)
|
||||||
return;
|
return;
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
var invoice = createInvoiceModel();
|
|
||||||
var design = getDesignJavascript();
|
|
||||||
|
|
||||||
if (! design) {
|
if (! design) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1421,10 +1443,6 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@if ($invoice->isSent() && config('ninja.lock_sent_invoices'))
|
|
||||||
return false;
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if ($invoice->is_deleted || $invoice->isClientTrashed())
|
@if ($invoice->is_deleted || $invoice->isClientTrashed())
|
||||||
if ($('#bulk_action').val() != 'restore') {
|
if ($('#bulk_action').val() != 'restore') {
|
||||||
return false;
|
return false;
|
||||||
@ -1569,7 +1587,6 @@
|
|||||||
submitBulkAction('delete');
|
submitBulkAction('delete');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function formEnterClick(event) {
|
function formEnterClick(event) {
|
||||||
if (event.keyCode === 13){
|
if (event.keyCode === 13){
|
||||||
if (event.target.type == 'textarea') {
|
if (event.target.type == 'textarea') {
|
||||||
|
@ -18,7 +18,14 @@
|
|||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
{!! Former::open('/bluevine/signup')->id('bluevineSignup') !!}
|
{!! Former::open('/bluevine/signup')->id('bluevineSignup') !!}
|
||||||
{!! trans('texts.bluevine_modal_text') !!}<br/>
|
<div class="pull-left">
|
||||||
|
{!! trans('texts.bluevine_modal_text') !!}
|
||||||
|
</div>
|
||||||
|
<div class="pull-right">
|
||||||
|
<br/>
|
||||||
|
<a class='btn btn-primary btn-sm' href='https://www.invoiceninja.com/blue-vine-invoice-factoring/' target="_blank">{{ trans('texts.learn_more') }}</a>
|
||||||
|
</div>
|
||||||
|
<div class="clearfix"></div>
|
||||||
<h3>{!! trans('texts.bluevine_create_account') !!}</h3>
|
<h3>{!! trans('texts.bluevine_create_account') !!}</h3>
|
||||||
{!! Former::text('name')->id('bluevine_name')->placeholder(trans('texts.name'))->value($user->first_name . ' ' . $user->last_name)->required() !!}
|
{!! Former::text('name')->id('bluevine_name')->placeholder(trans('texts.name'))->value($user->first_name . ' ' . $user->last_name)->required() !!}
|
||||||
{!! Former::text('email')->id('bluevine_email')->placeholder(trans('texts.email'))->value($user->email)->required() !!}
|
{!! Former::text('email')->id('bluevine_email')->placeholder(trans('texts.email'))->value($user->email)->required() !!}
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
{!! Former::text('name') !!}
|
{!! Former::text('name') !!}
|
||||||
|
|
||||||
{!! Former::text('task_rate')
|
{!! Former::text('task_rate')
|
||||||
|
->placeholder($project && $project->client->task_rate ? $project->client->present()->taskRate : $account->present()->taskRate)
|
||||||
->help('task_rate_help') !!}
|
->help('task_rate_help') !!}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -65,11 +66,13 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
var clients = {!! $clients !!};
|
var clients = {!! $clients !!};
|
||||||
|
var clientMap = {};
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
var $clientSelect = $('select#client_id');
|
var $clientSelect = $('select#client_id');
|
||||||
for (var i=0; i<clients.length; i++) {
|
for (var i=0; i<clients.length; i++) {
|
||||||
var client = clients[i];
|
var client = clients[i];
|
||||||
|
clientMap[client.public_id] = client;
|
||||||
var clientName = getClientDisplayName(client);
|
var clientName = getClientDisplayName(client);
|
||||||
if (!clientName) {
|
if (!clientName) {
|
||||||
continue;
|
continue;
|
||||||
@ -80,7 +83,15 @@
|
|||||||
$clientSelect.val({{ $clientPublicId }});
|
$clientSelect.val({{ $clientPublicId }});
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
$clientSelect.combobox({highlighter: comboboxHighlighter});
|
$clientSelect.combobox({highlighter: comboboxHighlighter}).change(function() {
|
||||||
|
var client = clientMap[$('#client_id').val()];
|
||||||
|
if (client && parseFloat(client.task_rate)) {
|
||||||
|
var rate = client.task_rate;
|
||||||
|
} else {
|
||||||
|
var rate = {{ $account->present()->taskRate }};
|
||||||
|
}
|
||||||
|
$('#task_rate').attr('placeholder', roundSignificant(rate));
|
||||||
|
});
|
||||||
|
|
||||||
@if ($clientPublicId)
|
@if ($clientPublicId)
|
||||||
$('#name').focus();
|
$('#name').focus();
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
{!! Former::text('time_log') !!}
|
{!! Former::text('time_log') !!}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row" onkeypress="formEnterClick(event)">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
@ -490,6 +490,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formEnterClick(event) {
|
||||||
|
if (event.keyCode === 13){
|
||||||
|
if (event.target.type == 'textarea') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
@if ($task && $task->trashed())
|
||||||
|
return;
|
||||||
|
@endif
|
||||||
|
submitAction('');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
$('input[type=radio]').change(function() {
|
$('input[type=radio]').change(function() {
|
||||||
onTaskTypeChange();
|
onTaskTypeChange();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user