mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Show tasks in client portal #1370
This commit is contained in:
parent
3ae70383af
commit
787602a992
@ -14,6 +14,7 @@ use App\Ninja\Repositories\CreditRepository;
|
||||
use App\Ninja\Repositories\DocumentRepository;
|
||||
use App\Ninja\Repositories\InvoiceRepository;
|
||||
use App\Ninja\Repositories\PaymentRepository;
|
||||
use App\Ninja\Repositories\TaskRepository;
|
||||
use App\Services\PaymentService;
|
||||
use Auth;
|
||||
use Barracuda\ArchiveStream\ZipArchive;
|
||||
@ -36,7 +37,14 @@ class ClientPortalController extends BaseController
|
||||
private $paymentRepo;
|
||||
private $documentRepo;
|
||||
|
||||
public function __construct(InvoiceRepository $invoiceRepo, PaymentRepository $paymentRepo, ActivityRepository $activityRepo, DocumentRepository $documentRepo, PaymentService $paymentService, CreditRepository $creditRepo)
|
||||
public function __construct(
|
||||
InvoiceRepository $invoiceRepo,
|
||||
PaymentRepository $paymentRepo,
|
||||
ActivityRepository $activityRepo,
|
||||
DocumentRepository $documentRepo,
|
||||
PaymentService $paymentService,
|
||||
CreditRepository $creditRepo,
|
||||
TaskRepository $taskRepo)
|
||||
{
|
||||
$this->invoiceRepo = $invoiceRepo;
|
||||
$this->paymentRepo = $paymentRepo;
|
||||
@ -44,6 +52,7 @@ class ClientPortalController extends BaseController
|
||||
$this->documentRepo = $documentRepo;
|
||||
$this->paymentService = $paymentService;
|
||||
$this->creditRepo = $creditRepo;
|
||||
$this->taskRepo = $taskRepo;
|
||||
}
|
||||
|
||||
public function view($invitationKey)
|
||||
@ -556,6 +565,46 @@ class ClientPortalController extends BaseController
|
||||
return $this->creditRepo->getClientDatatable($contact->client_id);
|
||||
}
|
||||
|
||||
public function taskIndex()
|
||||
{
|
||||
if (! $contact = $this->getContact()) {
|
||||
return $this->returnError();
|
||||
}
|
||||
|
||||
$account = $contact->account;
|
||||
$account->loadLocalizationSettings($contact->client);
|
||||
|
||||
if (! $contact->client->show_tasks_in_portal) {
|
||||
return redirect()->to($account->enable_client_portal_dashboard ? '/client/dashboard' : '/client/payment_methods/');
|
||||
}
|
||||
|
||||
if (! $account->enable_client_portal) {
|
||||
return $this->returnError();
|
||||
}
|
||||
|
||||
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
||||
|
||||
$data = [
|
||||
'color' => $color,
|
||||
'account' => $account,
|
||||
'title' => trans('texts.tasks'),
|
||||
'entityType' => ENTITY_TASK,
|
||||
'columns' => Utils::trans(['project', 'date', 'duration', 'description']),
|
||||
'sortColumn' => 1,
|
||||
];
|
||||
|
||||
return response()->view('public_list', $data);
|
||||
}
|
||||
|
||||
public function taskDatatable()
|
||||
{
|
||||
if (! $contact = $this->getContact()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->taskRepo->getClientDatatable($contact->client_id);
|
||||
}
|
||||
|
||||
public function documentIndex()
|
||||
{
|
||||
if (! $contact = $this->getContact()) {
|
||||
|
@ -66,6 +66,7 @@ class Authenticate
|
||||
if (! $contact) {
|
||||
return \Redirect::to('client/session_expired');
|
||||
}
|
||||
|
||||
$account = $contact->account;
|
||||
|
||||
if (Auth::guard('user')->check() && Auth::user('user')->account_id == $account->id) {
|
||||
@ -85,6 +86,10 @@ class Authenticate
|
||||
if (env('PHANTOMJS_SECRET') && $request->phantomjs_secret && hash_equals(env('PHANTOMJS_SECRET'), $request->phantomjs_secret)) {
|
||||
$authenticated = true;
|
||||
}
|
||||
|
||||
if ($authenticated) {
|
||||
$request->merge(['contact' => $contact]);
|
||||
}
|
||||
}
|
||||
|
||||
if (! $authenticated) {
|
||||
|
@ -59,10 +59,9 @@ class Client extends EntityModel
|
||||
'shipping_state',
|
||||
'shipping_postal_code',
|
||||
'shipping_country_id',
|
||||
'show_tasks_in_portal',
|
||||
];
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
@ -8,6 +8,7 @@ use App\Models\Task;
|
||||
use Auth;
|
||||
use Session;
|
||||
use DB;
|
||||
use Utils;
|
||||
|
||||
class TaskRepository extends BaseRepository
|
||||
{
|
||||
@ -101,6 +102,38 @@ class TaskRepository extends BaseRepository
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function getClientDatatable($clientId)
|
||||
{
|
||||
$query = DB::table('tasks')
|
||||
->leftJoin('projects', 'projects.id', '=', 'tasks.project_id')
|
||||
->where('tasks.client_id', '=', $clientId)
|
||||
->where('tasks.is_deleted', '=', false)
|
||||
->whereNull('tasks.invoice_id')
|
||||
->select(
|
||||
'tasks.description',
|
||||
'tasks.time_log',
|
||||
'tasks.time_log as duration',
|
||||
DB::raw("SUBSTRING(time_log, 3, 10) date"),
|
||||
'projects.name as project'
|
||||
);
|
||||
|
||||
$table = \Datatable::query($query)
|
||||
->addColumn('project', function ($model) {
|
||||
return $model->project;
|
||||
})
|
||||
->addColumn('date', function ($model) {
|
||||
return Task::calcStartTime($model);
|
||||
})
|
||||
->addColumn('duration', function ($model) {
|
||||
return Utils::formatTime(Task::calcDuration($model));
|
||||
})
|
||||
->addColumn('description', function ($model) {
|
||||
return $model->description;
|
||||
});
|
||||
|
||||
return $table->make();
|
||||
}
|
||||
|
||||
public function save($publicId, $data, $task = null)
|
||||
{
|
||||
if ($task) {
|
||||
|
@ -44,6 +44,7 @@ class ClientTransformer extends EntityTransformer
|
||||
* @SWG\Property(property="shipping_state", type="string", example="NY")
|
||||
* @SWG\Property(property="shipping_postal_code", type="string", example=10010)
|
||||
* @SWG\Property(property="shipping_country_id", type="integer", example=840)
|
||||
* @SWG\Property(property="show_tasks_in_portal", type="boolean", example=false)
|
||||
*/
|
||||
protected $defaultIncludes = [
|
||||
'contacts',
|
||||
@ -149,6 +150,7 @@ class ClientTransformer extends EntityTransformer
|
||||
'shipping_state' => $client->shipping_state,
|
||||
'shipping_postal_code' => $client->shipping_postal_code,
|
||||
'shipping_country_id' => (int) $client->shipping_country_id,
|
||||
'show_tasks_in_portal' => (bool) $client->show_tasks_in_portal,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ class AddSubdomainToLookups extends Migration
|
||||
$table->string('shipping_state')->nullable();
|
||||
$table->string('shipping_postal_code')->nullable();
|
||||
$table->unsignedInteger('shipping_country_id')->nullable();
|
||||
$table->boolean('show_tasks_in_portal')->default(0);
|
||||
$table->boolean('send_reminders')->default(1);
|
||||
});
|
||||
|
||||
Schema::table('clients', function ($table) {
|
||||
@ -68,6 +70,8 @@ class AddSubdomainToLookups extends Migration
|
||||
$table->dropColumn('shipping_state');
|
||||
$table->dropColumn('shipping_postal_code');
|
||||
$table->dropColumn('shipping_country_id');
|
||||
$table->dropColumn('show_tasks_in_portal');
|
||||
$table->dropColumn('send_reminders');
|
||||
});
|
||||
|
||||
Schema::table('account_gateways', function ($table) {
|
||||
|
@ -2544,6 +2544,7 @@ $LANG = array(
|
||||
'show_shipping_address_help' => 'Require client to provide their shipping address',
|
||||
'ship_to_billing_address' => 'Ship to billing address',
|
||||
'delivery_note' => 'Delivery Note',
|
||||
'show_tasks_in_portal' => 'Show tasks in the client portal'
|
||||
|
||||
);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
@if ($client)
|
||||
{!! Former::populate($client) !!}
|
||||
{!! Former::populateField('task_rate', floatval($client->task_rate) ? Utils::roundSignificant($client->task_rate) : '') !!}
|
||||
{!! Former::populateField('show_tasks_in_portal', intval($client->show_tasks_in_portal)) !!}
|
||||
{!! Former::hidden('public_id') !!}
|
||||
@else
|
||||
{!! Former::populateField('invoice_number_counter', 1) !!}
|
||||
@ -172,7 +173,7 @@
|
||||
<div role="tabpanel">
|
||||
<ul class="nav nav-tabs" role="tablist" style="border: none">
|
||||
<li role="presentation" class="active">
|
||||
<a href="#defaults" aria-controls="defaults" role="tab" data-toggle="tab">{{ trans('texts.defaults') }}</a>
|
||||
<a href="#settings" aria-controls="settings" role="tab" data-toggle="tab">{{ trans('texts.settings') }}</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a href="#notes" aria-controls="notes" role="tab" data-toggle="tab">{{ trans('texts.notes') }}</a>
|
||||
@ -183,7 +184,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content" style="padding-top:24px;">
|
||||
<div role="tabpanel" class="tab-pane active" id="defaults">
|
||||
<div role="tabpanel" class="tab-pane active" id="settings">
|
||||
{!! Former::select('currency_id')->addOption('','')
|
||||
->placeholder($account->currency ? $account->currency->name : '')
|
||||
->fromQuery($currencies, 'name', 'id') !!}
|
||||
@ -198,6 +199,10 @@
|
||||
{!! Former::text('task_rate')
|
||||
->placeholder($account->present()->taskRate)
|
||||
->help('task_rate_help') !!}
|
||||
{!! Former::checkbox('show_tasks_in_portal')
|
||||
->text(trans('texts.show_tasks_in_portal'))
|
||||
->label('client_portal')
|
||||
->value(1) !!}
|
||||
@endif
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="notes">
|
||||
|
@ -86,6 +86,11 @@
|
||||
{!! link_to('/client/dashboard', trans('texts.dashboard') ) !!}
|
||||
</li>
|
||||
@endif
|
||||
@if (request()->contact && request()->contact->client->show_tasks_in_portal)
|
||||
<li {!! Request::is('*client/tasks') ? 'class="active"' : '' !!}>
|
||||
{!! link_to('/client/tasks', trans('texts.tasks') ) !!}
|
||||
</li>
|
||||
@endif
|
||||
@if (isset($hasQuotes) && $hasQuotes)
|
||||
<li {!! Request::is('*client/quotes') ? 'class="active"' : '' !!}>
|
||||
{!! link_to('/client/quotes', trans('texts.quotes') ) !!}
|
||||
|
@ -36,6 +36,7 @@ Route::group(['middleware' => ['lookup:contact', 'auth:client']], function () {
|
||||
Route::post('client/invoices/auto_bill', 'ClientPortalController@setAutoBill');
|
||||
Route::get('client/documents', 'ClientPortalController@documentIndex');
|
||||
Route::get('client/payments', 'ClientPortalController@paymentIndex');
|
||||
Route::get('client/tasks', 'ClientPortalController@taskIndex');
|
||||
Route::get('client/dashboard/{contact_key?}', 'ClientPortalController@dashboard');
|
||||
Route::get('client/documents/js/{documents}/{filename}', 'ClientPortalController@getDocumentVFSJS');
|
||||
Route::get('client/documents/{invitation_key}/{documents}/{filename?}', 'ClientPortalController@getDocument');
|
||||
@ -47,6 +48,7 @@ Route::group(['middleware' => ['lookup:contact', 'auth:client']], function () {
|
||||
Route::get('api/client.recurring_invoices', ['as' => 'api.client.recurring_invoices', 'uses' => 'ClientPortalController@recurringInvoiceDatatable']);
|
||||
Route::get('api/client.documents', ['as' => 'api.client.documents', 'uses' => 'ClientPortalController@documentDatatable']);
|
||||
Route::get('api/client.payments', ['as' => 'api.client.payments', 'uses' => 'ClientPortalController@paymentDatatable']);
|
||||
Route::get('api/client.tasks', ['as' => 'api.client.tasks', 'uses' => 'ClientPortalController@taskDatatable']);
|
||||
Route::get('api/client.activity', ['as' => 'api.client.activity', 'uses' => 'ClientPortalController@activityDatatable']);
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user