mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-09 20:52:56 +01: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)
|
||||
{
|
||||
$data = [
|
||||
'account' => auth()->user()->account,
|
||||
'project' => null,
|
||||
'method' => 'POST',
|
||||
'url' => 'projects',
|
||||
@ -67,6 +68,7 @@ class ProjectController extends BaseController
|
||||
$project = $request->entity();
|
||||
|
||||
$data = [
|
||||
'account' => auth()->user()->account,
|
||||
'project' => $project,
|
||||
'method' => 'PUT',
|
||||
'url' => 'projects/' . $project->public_id,
|
||||
|
@ -11,7 +11,7 @@ class TwoFactorController extends Controller
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
if ($user->google_2fa_secret || ! $user->phone) {
|
||||
if ($user->google_2fa_secret || ! $user->phone || ! $user->confirmed) {
|
||||
return redirect('/settings/user_details');
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ class TwoFactorController extends Controller
|
||||
$user = auth()->user();
|
||||
$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->save();
|
||||
|
||||
|
@ -89,6 +89,11 @@ class Utils
|
||||
return env('NINJA_DEV') == 'true';
|
||||
}
|
||||
|
||||
public static function isTimeTracker()
|
||||
{
|
||||
return array_get($_SERVER, 'HTTP_USER_AGENT') == TIME_TRACKER_USER_AGENT;
|
||||
}
|
||||
|
||||
public static function requireHTTPS()
|
||||
{
|
||||
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()),
|
||||
'invoice' => $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_amount' => $payment ? $account->formatMoney($payment->amount, $payment) : null,
|
||||
'adjustment' => $this->adjustment ? $account->formatMoney($this->adjustment, $this) : null,
|
||||
|
@ -15,8 +15,17 @@ class ActivityDatatable extends EntityDatatable
|
||||
'activities.id',
|
||||
function ($model) {
|
||||
$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;
|
||||
$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 string
|
||||
*/
|
||||
public function taskRate()
|
||||
{
|
||||
if ($this->entity->task_rate) {
|
||||
return Utils::roundSignificant($this->entity->task_rate);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 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',
|
||||
'email_will_be_sent_on' => 'Note: the email will be sent on :date.',
|
||||
'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,21 +50,22 @@
|
||||
!!}
|
||||
@endif
|
||||
|
||||
@if ($user->google_2fa_secret)
|
||||
{!! Former::checkbox('enable_two_factor')
|
||||
->help(trans('texts.enable_two_factor_help'))
|
||||
->text(trans('texts.enable'))
|
||||
->value(1) !!}
|
||||
@elseif ($user->phone)
|
||||
{!! Former::plaintext('enable_two_factor')->value(
|
||||
Button::primary(trans('texts.enable'))->asLinkTo(url('settings/enable_two_factor'))->small()
|
||||
)->help('enable_two_factor_help') !!}
|
||||
@else
|
||||
{!! Former::plaintext('enable_two_factor')
|
||||
->value('<span class="text-muted">' . trans('texts.set_phone_for_two_factor') . '</span>') !!}
|
||||
@if ($user->confirmed)
|
||||
@if ($user->google_2fa_secret)
|
||||
{!! Former::checkbox('enable_two_factor')
|
||||
->help(trans('texts.enable_two_factor_help'))
|
||||
->text(trans('texts.enable'))
|
||||
->value(1) !!}
|
||||
@elseif ($user->phone)
|
||||
{!! Former::plaintext('enable_two_factor')->value(
|
||||
Button::primary(trans('texts.enable'))->asLinkTo(url('settings/enable_two_factor'))->small()
|
||||
)->help('enable_two_factor_help') !!}
|
||||
@else
|
||||
{!! Former::plaintext('enable_two_factor')
|
||||
->value('<span class="text-muted">' . trans('texts.set_phone_for_two_factor') . '</span>') !!}
|
||||
@endif
|
||||
@endif
|
||||
|
||||
|
||||
{!! Former::checkbox('dark_mode')
|
||||
->help(trans('texts.dark_mode_help'))
|
||||
->text(trans('texts.enable'))
|
||||
|
@ -83,7 +83,11 @@
|
||||
{!! link_to('/recover_password', trans('texts.recover_password')) !!}
|
||||
</div>
|
||||
<div class="col-md-5 col-sm-12">
|
||||
{!! link_to(NINJA_WEB_URL.'/knowledgebase/', trans('texts.knowledge_base'), ['target' => '_blank']) !!}
|
||||
@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']) !!}
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@ -111,8 +115,13 @@
|
||||
$('#email').focus();
|
||||
}
|
||||
|
||||
@if (array_get($_SERVER, 'HTTP_USER_AGENT') == TIME_TRACKER_USER_AGENT)
|
||||
@if (Utils::isTimeTracker())
|
||||
if (isStorageSupported()) {
|
||||
var selfHostUrl = localStorage.getItem('last:time_tracker:url');
|
||||
if (selfHostUrl) {
|
||||
location.href = selfHostUrl;
|
||||
return;
|
||||
}
|
||||
$('#email').change(function() {
|
||||
localStorage.setItem('last:time_tracker:email', $('#email').val());
|
||||
})
|
||||
@ -124,6 +133,29 @@
|
||||
}
|
||||
@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>
|
||||
|
||||
@endsection
|
||||
|
@ -158,6 +158,7 @@
|
||||
->help(trans('texts.payment_terms_help')) !!}
|
||||
@if ($account->isModuleEnabled(ENTITY_TASK))
|
||||
{!! Former::text('task_rate')
|
||||
->placeholder($account->present()->taskRate)
|
||||
->help('task_rate_help') !!}
|
||||
@endif
|
||||
{!! Former::select('size_id')->addOption('','')
|
||||
|
@ -536,7 +536,10 @@
|
||||
@if ($invoice->isClientTrashed())
|
||||
<!-- do nothing -->
|
||||
@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
|
||||
@if (!$invoice->is_deleted)
|
||||
@if ($invoice->isSent())
|
||||
@ -1188,6 +1191,8 @@
|
||||
}
|
||||
|
||||
var origInvoiceNumber = false;
|
||||
var checkedInvoiceBalances = false;
|
||||
|
||||
function getPDFString(cb, force) {
|
||||
@if (! $invoice->id && $account->credit_number_counter > 0)
|
||||
var total = model.invoice().totals.rawTotal();
|
||||
@ -1201,13 +1206,30 @@
|
||||
}
|
||||
@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)
|
||||
return;
|
||||
@endif
|
||||
|
||||
var invoice = createInvoiceModel();
|
||||
var design = getDesignJavascript();
|
||||
|
||||
if (! design) {
|
||||
return;
|
||||
}
|
||||
@ -1421,10 +1443,6 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
@if ($invoice->isSent() && config('ninja.lock_sent_invoices'))
|
||||
return false;
|
||||
@endif
|
||||
|
||||
@if ($invoice->is_deleted || $invoice->isClientTrashed())
|
||||
if ($('#bulk_action').val() != 'restore') {
|
||||
return false;
|
||||
@ -1569,7 +1587,6 @@
|
||||
submitBulkAction('delete');
|
||||
});
|
||||
}
|
||||
|
||||
function formEnterClick(event) {
|
||||
if (event.keyCode === 13){
|
||||
if (event.target.type == 'textarea') {
|
||||
|
@ -18,7 +18,14 @@
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
{!! 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>
|
||||
{!! 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() !!}
|
||||
|
@ -41,6 +41,7 @@
|
||||
{!! Former::text('name') !!}
|
||||
|
||||
{!! Former::text('task_rate')
|
||||
->placeholder($project && $project->client->task_rate ? $project->client->present()->taskRate : $account->present()->taskRate)
|
||||
->help('task_rate_help') !!}
|
||||
|
||||
</div>
|
||||
@ -65,11 +66,13 @@
|
||||
<script>
|
||||
|
||||
var clients = {!! $clients !!};
|
||||
var clientMap = {};
|
||||
|
||||
$(function() {
|
||||
var $clientSelect = $('select#client_id');
|
||||
for (var i=0; i<clients.length; i++) {
|
||||
var client = clients[i];
|
||||
clientMap[client.public_id] = client;
|
||||
var clientName = getClientDisplayName(client);
|
||||
if (!clientName) {
|
||||
continue;
|
||||
@ -80,7 +83,15 @@
|
||||
$clientSelect.val({{ $clientPublicId }});
|
||||
@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)
|
||||
$('#name').focus();
|
||||
|
@ -41,7 +41,7 @@
|
||||
{!! Former::text('time_log') !!}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="row" onkeypress="formEnterClick(event)">
|
||||
<div class="col-md-12">
|
||||
|
||||
<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() {
|
||||
$('input[type=radio]').change(function() {
|
||||
onTaskTypeChange();
|
||||
|
Loading…
Reference in New Issue
Block a user