mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Working on manual send reminders #1234
This commit is contained in:
parent
3e4528e340
commit
d38101545f
@ -4,12 +4,20 @@ namespace App\Models;
|
||||
|
||||
use Auth;
|
||||
use Eloquent;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
|
||||
/**
|
||||
* Class Activity.
|
||||
*/
|
||||
class Activity extends Eloquent
|
||||
{
|
||||
use PresentableTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $presenter = 'App\Ninja\Presenters\ActivityPresenter';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
|
@ -9,6 +9,7 @@ use App\Events\QuoteInvitationWasEmailed;
|
||||
use App\Events\QuoteWasCreated;
|
||||
use App\Events\QuoteWasUpdated;
|
||||
use App\Libraries\CurlUtils;
|
||||
use App\Models\Activity;
|
||||
use DateTime;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
@ -1441,6 +1442,16 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
|
||||
return $statuses;
|
||||
}
|
||||
|
||||
public function emailHistory()
|
||||
{
|
||||
return Activity::scope()
|
||||
->with(['contact'])
|
||||
->whereInvoiceId($this->id)
|
||||
->whereIn('activity_type_id', [ACTIVITY_TYPE_EMAIL_INVOICE, ACTIVITY_TYPE_EMAIL_QUOTE])
|
||||
->orderBy('id', 'desc')
|
||||
->get();
|
||||
}
|
||||
}
|
||||
|
||||
Invoice::creating(function ($invoice) {
|
||||
|
39
app/Ninja/Presenters/ActivityPresenter.php
Normal file
39
app/Ninja/Presenters/ActivityPresenter.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ninja\Presenters;
|
||||
|
||||
use Laracasts\Presenter\Presenter;
|
||||
use Utils;
|
||||
|
||||
class ActivityPresenter extends Presenter
|
||||
{
|
||||
public function createdAt()
|
||||
{
|
||||
return Utils::timestampToDateTimeString(strtotime($this->entity->created_at));
|
||||
}
|
||||
|
||||
public function createdAtDate()
|
||||
{
|
||||
return Utils::dateToString($this->entity->created_at);
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
if ($this->entity->is_system) {
|
||||
return '<i>' . trans('texts.system') . '</i>';
|
||||
} else {
|
||||
return $this->entity->user->getDisplayName();
|
||||
}
|
||||
}
|
||||
|
||||
public function notes()
|
||||
{
|
||||
if ($this->entity->notes) {
|
||||
return trans('texts.notes_' . $this->entity->notes);
|
||||
} elseif (in_array($this->entity->activity_type_id, [ACTIVITY_TYPE_EMAIL_INVOICE, ACTIVITY_TYPE_EMAIL_QUOTE])) {
|
||||
return trans('texts.initial_email');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace App\Ninja\Presenters;
|
||||
|
||||
use App\Libraries\Skype\InvoiceCard;
|
||||
use App\Models\Activity;
|
||||
use Carbon;
|
||||
use DropdownButton;
|
||||
use stdClass;
|
||||
|
@ -494,7 +494,7 @@ $LANG = array(
|
||||
'email_address' => 'Email address',
|
||||
'lets_go' => 'Let\'s go',
|
||||
'password_recovery' => 'Password Recovery',
|
||||
'send_email' => 'Send email',
|
||||
'send_email' => 'Send Email',
|
||||
'set_password' => 'Set Password',
|
||||
'converted' => 'Converted',
|
||||
'email_approved' => 'Email me when a quote is <b>approved</b>',
|
||||
@ -2347,6 +2347,13 @@ $LANG = array(
|
||||
'inactivity_logout' => 'Due to inactivity, you have been automatically logged out.',
|
||||
'mark_active' => 'Mark Active',
|
||||
'send_automatically' => 'Send Automatically',
|
||||
'template' => 'Template',
|
||||
'initial_email' => 'Initial Email',
|
||||
'invoice_not_emailed' => 'This invoice hasn\'t been emailed.',
|
||||
'quote_not_emailed' => 'This quote hasn\'t been emailed.',
|
||||
'days_ago' => ':count day ago|:count days ago',
|
||||
'sent_by' => 'Sent by :user',
|
||||
'recipients' => 'Recipients',
|
||||
|
||||
);
|
||||
|
||||
|
@ -799,6 +799,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('invoices.email')
|
||||
|
||||
{!! Former::close() !!}
|
||||
</form>
|
||||
|
||||
@ -1284,24 +1286,33 @@
|
||||
return;
|
||||
}
|
||||
|
||||
sweetConfirm(function() {
|
||||
model.invoice().is_public(true);
|
||||
var accountLanguageId = parseInt({{ $account->language_id ?: '0' }});
|
||||
var clientLanguageId = parseInt(model.invoice().client().language_id()) || 0;
|
||||
var attachPDF = {{ $account->attachPDF() ? 'true' : 'false' }};
|
||||
|
||||
// if they aren't attaching the pdf no need to generate it
|
||||
if ( ! attachPDF) {
|
||||
submitAction('email');
|
||||
// if the client's language is different then we can't use the browser version of the PDF
|
||||
} else if (clientLanguageId && clientLanguageId != accountLanguageId) {
|
||||
submitAction('email');
|
||||
} else {
|
||||
preparePdfData('email');
|
||||
}
|
||||
}, getSendToEmails());
|
||||
$('#recipients').html(getSendToEmails());
|
||||
$('#emailModal').modal('show');
|
||||
}
|
||||
|
||||
function onConfirmEmailClick() {
|
||||
model.invoice().is_public(true);
|
||||
var accountLanguageId = parseInt({{ $account->language_id ?: '0' }});
|
||||
var clientLanguageId = parseInt(model.invoice().client().language_id()) || 0;
|
||||
var attachPDF = {{ $account->attachPDF() ? 'true' : 'false' }};
|
||||
|
||||
// if they aren't attaching the pdf no need to generate it
|
||||
if ( ! attachPDF) {
|
||||
submitAction('email');
|
||||
// if the client's language is different then we can't use the browser version of the PDF
|
||||
} else if (clientLanguageId && clientLanguageId != accountLanguageId) {
|
||||
submitAction('email');
|
||||
} else {
|
||||
preparePdfData('email');
|
||||
}
|
||||
}
|
||||
|
||||
@if (Utils::isNinjaDev())
|
||||
$(function() {
|
||||
onEmailClick();
|
||||
})
|
||||
@endif
|
||||
|
||||
function onSaveDraftClick() {
|
||||
model.invoice().is_public(false);
|
||||
onSaveClick();
|
||||
@ -1310,7 +1321,7 @@
|
||||
function onMarkSentClick() {
|
||||
if (model.invoice().is_recurring()) {
|
||||
// warn invoice will be emailed when saving new recurring invoice
|
||||
var text = getSendToEmails() + '\n' + "{!! trans("texts.confirm_recurring_timing") !!}";
|
||||
var text = '\n' + getSendToEmails() + '\n\n' + "{!! trans("texts.confirm_recurring_timing") !!}";
|
||||
var title = "{!! trans("texts.confirm_recurring_email_$entityType") !!}";
|
||||
sweetConfirm(function() {
|
||||
model.invoice().is_public(true);
|
||||
|
93
resources/views/invoices/email.blade.php
Normal file
93
resources/views/invoices/email.blade.php
Normal file
@ -0,0 +1,93 @@
|
||||
<div class="modal fade" id="emailModal" tabindex="-1" role="dialog" aria-labelledby="emailModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" style="min-width:150px">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title" id="emailModalLabel">{{ trans('texts.email_invoice') }}</h4>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="panel-body">
|
||||
|
||||
{!! Former::plaintext('recipients')
|
||||
->value('') !!}
|
||||
|
||||
{!! Former::select('template')
|
||||
->options([
|
||||
'initial' => trans('texts.initial_email'),
|
||||
'reminder1' => trans('texts.first_reminder'),
|
||||
'reminder2' => trans('texts.second_reminder'),
|
||||
'reminder3' => trans('texts.third_reminder'),
|
||||
]) !!}
|
||||
|
||||
<br/>
|
||||
<div role="tabpanel">
|
||||
<ul class="nav nav-tabs" role="tablist" style="border: none">
|
||||
<li role="presentation" class="active">
|
||||
<a href="#preview" aria-controls="preview" role="tab" data-toggle="tab">{{ trans('texts.preview') }}</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a href="#customize" aria-controls="customize" role="tab" data-toggle="tab">{{ trans('texts.customize') }}</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a href="#history" aria-controls="history" role="tab" data-toggle="tab">{{ trans('texts.history') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="preview">
|
||||
<div id="emailSubject"></div>
|
||||
<div id="emailBody"></div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="customize">
|
||||
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="history">
|
||||
<br/>
|
||||
@if (count($activities = $invoice->emailHistory()))
|
||||
<table class="table table-striped data-table">
|
||||
<tr>
|
||||
<th>{{ trans('texts.template')}}</th>
|
||||
<th>{{ trans('texts.contact')}}</th>
|
||||
<th>{{ trans('texts.date')}}</th>
|
||||
</tr>
|
||||
@foreach ($activities as $activity)
|
||||
<tr>
|
||||
<td>{{ $activity->present()->notes }}</td>
|
||||
<td>
|
||||
<span title="{{ trans('texts.sent_by', ['user' => $activity->present()->user]) }}">
|
||||
{{ $activity->contact->getDisplayName() }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span title="{{ $activity->present()->createdAt }}">
|
||||
{{ $activity->present()->createdAtDate }} - {{ trans_choice('texts.days_ago', $activity->created_at->diffInDays()) }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</table>
|
||||
@else
|
||||
<center style="font-size:16px;color:#888888;padding-top:20px;">
|
||||
{{ trans("texts.{$invoice->getEntityType()}_not_emailed") }}
|
||||
</center>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer" style="margin-top: 0px">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('texts.cancel') }}</button>
|
||||
<button type="button" class="btn btn-info" onclick="onConfirmEmailClick()">{{ trans('texts.send_email') }}</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
</script>
|
@ -641,13 +641,13 @@ function ContactModel(data) {
|
||||
self.displayName = ko.computed(function() {
|
||||
var str = '';
|
||||
if (self.first_name() || self.last_name()) {
|
||||
str += (self.first_name() || '') + ' ' + (self.last_name() || '') + '\n';
|
||||
str += (self.first_name() || '') + ' ' + (self.last_name() || '') + ' ';
|
||||
}
|
||||
if (self.email()) {
|
||||
str += self.email() + '\n';
|
||||
str += '<' + self.email() + '>';
|
||||
}
|
||||
|
||||
return str;
|
||||
return str + '<br/>';
|
||||
});
|
||||
|
||||
self.email.display = ko.computed(function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user