Compare commits
4 commits
67548a7315
...
62b4f49d4d
Author | SHA1 | Date | |
---|---|---|---|
62b4f49d4d | |||
829dcb49ad | |||
52985cd5a0 | |||
6fbaf4bfc3 |
9 changed files with 261 additions and 11 deletions
|
@ -1,3 +1,9 @@
|
|||
0.4.0
|
||||
|
||||
* Display all Customers when using an admin account.
|
||||
* Add the ability to set the Mailbox when editing a Customer.
|
||||
* When editing a Customer, pre-select its current Mailbox.
|
||||
|
||||
0.3.0
|
||||
|
||||
* Improve the initial linking of Customers to Mailboxes, to include Customers linked with several Conversations.
|
||||
|
|
|
@ -19,7 +19,7 @@ You have been warned.
|
|||
### Install the package with composer
|
||||
|
||||
```
|
||||
composer require "millions-missing-france/freescout-restricted-customers" "0.3.1"
|
||||
composer require "millions-missing-france/freescout-restricted-customers" "0.4.0"
|
||||
```
|
||||
|
||||
### Edit the application routes
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "millions-missing-france/freescout-restricted-customers",
|
||||
"description": "Freescout restricted customers - Restrict access to Freescout customers to specific mailboxes",
|
||||
"version": "0.3.1",
|
||||
"version": "0.4.0",
|
||||
"type": "library",
|
||||
"license": ["AGPL-3.0-only"],
|
||||
"authors": [
|
||||
|
|
175
resources/views/conversations/search.blade.php
Normal file
175
resources/views/conversations/search.blade.php
Normal file
|
@ -0,0 +1,175 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('title', ($q ? $q.' - ' : '').strip_tags(Eventy::filter('search.title', __('Search'))))
|
||||
@section('body_class', 'body-search')
|
||||
|
||||
@section('sidebar')
|
||||
@include('partials/sidebar_menu_toggle')
|
||||
<div class="sidebar-title">
|
||||
{!! Eventy::filter('search.title', __('Search')) !!}
|
||||
</div>
|
||||
<ul class="sidebar-menu sidebar-menu-noicons">
|
||||
@if (!$recent || (count($recent) == 1 && $recent[0] == $q))
|
||||
@else
|
||||
<li class="no-link"><span class="text-help">{{ __('Recent') }}</span></li>
|
||||
@foreach ($recent as $recent_query)
|
||||
@if ($recent_query != $q)
|
||||
<li class="menu-link menu-padded"><a href="{{ route('conversations.search', ['q' => $recent_query, 'mode' => $mode])}}">{{ $recent_query }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
<li class="no-link"><span class="text-help">{{ __('Filters') }}</span></li>
|
||||
@foreach ($filters_list as $filter)
|
||||
<li class="menu-link menu-padded">
|
||||
<a href="#" data-filter="{{ $filter }}" @if (isset($filters[$filter]))class="active"@endif>{{ mb_strtolower(__(ucwords($filter))) }}:</a>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="section-heading section-search">
|
||||
<form action="{{ route('conversations.search') }}">
|
||||
|
||||
@if (request()->x_embed)
|
||||
<input type="hidden" name="x_embed" value="{{ request()->x_embed }}" />
|
||||
@endif
|
||||
|
||||
@if (!empty($filters['custom']))
|
||||
<input type="hidden" name="f[custom]" value="{{ $filters['custom'] }}" />
|
||||
@endif
|
||||
|
||||
@if ($mode != App\Conversation::SEARCH_MODE_CONV)
|
||||
<input type="hidden" name="mode" value="{{ $mode }}" />
|
||||
@endif
|
||||
|
||||
<div class="row" id="search-filters">
|
||||
<div class="col-sm-6 form-group @if (isset($filters['assigned'])) active @endif" data-filter="assigned">
|
||||
<label>{{ __('Assigned') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<select name="f[assigned]" class="form-control" @if (empty($filters['assigned'])) disabled @endif>
|
||||
<option value=""></option>
|
||||
<option value="{{ App\Conversation::USER_UNASSIGNED }}" @if (!empty($filters['assigned']) && $filters['assigned'] == App\Conversation::USER_UNASSIGNED)selected="selected"@endif>{{ __('Unassigned') }}</option>
|
||||
@foreach ($users as $user)
|
||||
<option value="{{ $user->id }}" @if (!empty($filters['assigned']) && $filters['assigned'] == $user->id)selected="selected"@endif>{{ $user->getFullName() }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['customer'])) active @endif" data-filter="customer">
|
||||
<label>{{ __('Customer') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<div class="controls">
|
||||
<select class="form-control" name="f[customer]" id="search-filter-customer" @if (empty($filters['customer'])) disabled @endif/>
|
||||
@if (!empty($filters['customer']) && !empty($filters_data['customer']))
|
||||
<option value="{{ $filters_data['customer']->id }}" selected="selected">{{ $filters_data['customer']->getEmailAndName() }}</option>
|
||||
@endif
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['mailbox'])) active @endif" data-filter="mailbox">
|
||||
<label>{{ __('Mailbox') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<select name="f[mailbox]" class="form-control" @if (empty($filters['mailbox'])) disabled @endif>
|
||||
<option value=""></option>
|
||||
@foreach ($mailboxes as $mailbox_item)
|
||||
<option value="{{ $mailbox_item->id }}" @if (!empty($filters['mailbox']) && $filters['mailbox'] == $mailbox_item->id)selected="selected"@endif>{{ $mailbox_item->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['status'])) active @endif" data-filter="status">
|
||||
<label>{{ __('Status') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<select name="f[status][]" class="form-control filter-multiple" multiple @if (empty($filters['status'])) disabled @endif>
|
||||
{{--<option value=""></option>--}}
|
||||
@foreach (App\Conversation::$statuses as $status_id => $dummy)
|
||||
<option value="{{ $status_id }}" @if (!empty($filters['status']) && in_array($status_id, $filters['status']))selected="selected"@endif>{{ App\Conversation::statusCodeToName($status_id) }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['state'])) active @endif" data-filter="state">
|
||||
<label>{{ __('State') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<select name="f[state][]" class="form-control filter-multiple" multiple @if (empty($filters['state'])) disabled @endif>
|
||||
{{--<option value=""></option>--}}
|
||||
@foreach (App\Conversation::$states as $state_id => $dummy)
|
||||
<option value="{{ $state_id }}" @if (!empty($filters['state']) && in_array($state_id, $filters['state']))selected="selected"@endif>{{ App\Conversation::stateCodeToName($state_id) }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['subject'])) active @endif" data-filter="subject">
|
||||
<label>{{ __('Subject') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<input type="text" name="f[subject]" value="{{ $filters['subject'] ?? ''}}" class="form-control" @if (empty($filters['subject'])) disabled @endif>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['attachments'])) active @endif" data-filter="attachments">
|
||||
<label>{{ __('Attachments') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<select name="f[attachments]" class="form-control" @if (empty($filters['attachments'])) disabled @endif>
|
||||
<option value=""></option>
|
||||
<option value="yes" @if (!empty($filters['attachments']) && $filters['attachments'] == 'yes')selected="selected"@endif>{{ __('Yes') }}</option>
|
||||
<option value="no" @if (!empty($filters['attachments']) && $filters['attachments'] == 'no')selected="selected"@endif>{{ __('No') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['type'])) active @endif" data-filter="type">
|
||||
<label>{{ __('Type') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<select name="f[type]" class="form-control" @if (empty($filters['type'])) disabled @endif>
|
||||
<option value=""></option>
|
||||
@foreach (App\Conversation::$types as $type_id => $dummy)
|
||||
<option value="{{ $type_id }}" @if (!empty($filters['type']) && $filters['type'] == $type_id)selected="selected"@endif>{{ App\Conversation::typeToName($type_id) }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['body'])) active @endif" data-filter="body">
|
||||
<label>{{ __('Body') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<input type="text" name="f[body]" value="{{ $filters['body'] ?? ''}}" class="form-control" @if (empty($filters['body'])) disabled @endif>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['number'])) active @endif" data-filter="number">
|
||||
<label>{{ __('Number') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<input type="text" name="f[number]" value="{{ $filters['number'] ?? ''}}" class="form-control" @if (empty($filters['number'])) disabled @endif>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['following'])) active @endif" data-filter="following">
|
||||
<label>{{ __('Following') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<select name="f[following]" class="form-control" @if (empty($filters['following'])) disabled @endif>
|
||||
<option value=""></option>
|
||||
<option value="yes" @if (!empty($filters['following']) && $filters['following'] == 'yes')selected="selected"@endif>{{ __('Yes') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['id'])) active @endif" data-filter="id">
|
||||
<label>{{ __('ID') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<input type="text" name="f[id]" value="{{ $filters['id'] ?? ''}}" class="form-control" @if (empty($filters['id'])) disabled @endif>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['after'])) active @endif" data-filter="after">
|
||||
<label>{{ __('After') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<input type="text" name="f[after]" value="{{ $filters['after'] ?? ''}}" class="form-control input-date" @if (empty($filters['after'])) disabled @endif>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group @if (isset($filters['before'])) active @endif" data-filter="before">
|
||||
<label>{{ __('Before') }} <b class="remove" data-toggle="tooltip" title="{{ __('Remove filter') }}">×</b></label>
|
||||
<input type="text" name="f[before]" value="{{ $filters['before'] ?? ''}}" class="form-control input-date" @if (empty($filters['before'])) disabled @endif>
|
||||
</div>
|
||||
@action('search.display_filters', $filters, $filters_data, $mode)
|
||||
</div>
|
||||
|
||||
<div class="input-group input-group-lg1">
|
||||
<input type="text" class="form-control" name="q" value="{{ $q }}">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="submit">{{ __('Search') }}</button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="search-results">
|
||||
<ul class="nav nav-tabs nav-tabs-main margin-top">
|
||||
@if (Eventy::filter('search.is_tab_visible', true, App\Conversation::SEARCH_MODE_CONV))
|
||||
<li @if ($mode == App\Conversation::SEARCH_MODE_CONV)class="active search-tab-conv"@endif><a href="{{ \Helper::fixProtocol(request()->fullUrlWithQuery(['mode' => App\Conversation::SEARCH_MODE_CONV])) }}">{{ __('Conversations') }} <b>({{ $conversations->total() }})</b>@action('search.conversations_tab_append', $filters, $conversations->total())</a></li>
|
||||
@endif
|
||||
<li @if ($mode == App\Conversation::SEARCH_MODE_CUSTOMERS)class="active"@endif><a href="{{ \Helper::fixProtocol(request()->fullUrlWithQuery(['mode' => App\Conversation::SEARCH_MODE_CUSTOMERS])) }}">{{ __('Customers') }} <b>({{ $customers->total() }})</b></a></li>
|
||||
</ul>
|
||||
@if ($mode == App\Conversation::SEARCH_MODE_CONV)
|
||||
@include('conversations/conversations_table', ['mailbox' => $search_mailbox, 'params' => ['target_blank' => true, 'show_mailbox' => (count(Auth::user()->mailboxesCanView(true)) > 1)]])
|
||||
@else
|
||||
@include('freescout-restricted-customers::customers/partials/customers_table')
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@include('partials/include_datepicker')
|
||||
|
||||
@section('javascript')
|
||||
@parent
|
||||
searchInit();
|
||||
@endsection
|
26
resources/views/customers/partials/customers_table.blade.php
Normal file
26
resources/views/customers/partials/customers_table.blade.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
@if (count($customers))
|
||||
<div class="table-customers" data-page="{{ (int)request()->get('page', 1) }}">
|
||||
<div class="container">
|
||||
<div class="card-list margin-top">
|
||||
@foreach ($customers as $customer)
|
||||
<a href="{{ Eventy::filter('customer.card.url', route('customers.update', ['id' => $customer->id]), $customer) }}" class="card hover-shade" @action('customer.card.link', $customer) >
|
||||
<img src="{{ $customer->getPhotoUrl() }}" />
|
||||
@if ($customer->mailbox == null)
|
||||
<p style="font-size:12px; color: red;">{{ __('Warning: no mailbox') }}</p>
|
||||
@endif
|
||||
<h4 title="{{ $customer->first_name }} {{ $customer->last_name }}">{{ $customer->first_name }} {{ $customer->last_name }}</h4>
|
||||
<p class="text-truncate"><small>{{ $customer->getEmailOrPhone() }}</small></p>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if ($customers->lastPage() > 1)
|
||||
<div class="customers-pager">
|
||||
{{ $customers->links('conversations/conversations_pagination') }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
@include('partials/empty', ['empty_text' => __('No customers found')])
|
||||
@endif
|
|
@ -17,10 +17,18 @@
|
|||
<div>
|
||||
<div class="input-group input-group-flex input-sized-lg">
|
||||
<select class="form-control" name="mailbox" required>
|
||||
<!-- TODO: Automatically select the Mailbox currently set, if there is one. -->
|
||||
@if($customer->mailbox_id == null)
|
||||
<option value="" disabled selected>---</option>
|
||||
@endif
|
||||
@foreach($mailboxes as $mailbox)
|
||||
<option value="{{ $mailbox->id }}">{{ $mailbox->name }}</option>
|
||||
<option
|
||||
value="{{ $mailbox->id }}"
|
||||
@if($mailbox->id == $customer->mailbox_id)
|
||||
selected
|
||||
@endif
|
||||
>
|
||||
{{ $mailbox->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
|
23
resources/views/customers/update.blade.php
Normal file
23
resources/views/customers/update.blade.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('title_full', $customer->getFullName(true).' - '.__('Customer Profile'))
|
||||
@section('body_class', 'sidebar-no-height')
|
||||
|
||||
@section('body_attrs')@parent data-customer_id="{{ $customer->id }}"@endsection
|
||||
|
||||
@section('sidebar')
|
||||
<div class="profile-preview">
|
||||
@include('customers/profile_menu')
|
||||
@include('customers/profile_snippet')
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
@include('customers/profile_tabs')
|
||||
@include('freescout-restricted-customers::customers/partials/edit_form')
|
||||
@endsection
|
||||
|
||||
@section('javascript')
|
||||
@parent
|
||||
multiInputInit();
|
||||
@endsection
|
|
@ -7,6 +7,7 @@
|
|||
namespace MillionsMissingFrance\FreescoutRestrictedCustomers\Http\Controllers;
|
||||
|
||||
use App\Conversation;
|
||||
use App\User;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\ConversationsController as BaseConversationsController;
|
||||
use MillionsMissingFrance\FreescoutRestrictedCustomers\Customer;
|
||||
|
@ -90,7 +91,7 @@ class ConversationsController extends BaseConversationsController {
|
|||
$search_mailbox = $mailboxes[0];
|
||||
}
|
||||
|
||||
return view('conversations/search', [
|
||||
return view('freescout-restricted-customers::conversations/search', [
|
||||
'folder' => $folder,
|
||||
'q' => $request->q,
|
||||
'filters' => $filters,
|
||||
|
@ -154,9 +155,11 @@ class ConversationsController extends BaseConversationsController {
|
|||
$query->orWhere('customers.phones', $like_op, '%"'.$phone_numeric.'"%');
|
||||
}
|
||||
|
||||
})
|
||||
});
|
||||
// Restrict the query to the Customers the current User is allowed to access.
|
||||
->whereIn('customers.mailbox_id', $mailbox_ids);
|
||||
if ( $user->role != User::ROLE_ADMIN ) {
|
||||
$query_customers->whereIn('customers.mailbox_id', $mailbox_ids);
|
||||
}
|
||||
|
||||
if (!empty($filters['mailbox']) && in_array($filters['mailbox'], $mailbox_ids)) {
|
||||
$query_customers->where('customers.mailbox_id', '=', $filters['mailbox']);
|
||||
|
|
|
@ -22,6 +22,11 @@ class CustomersController extends BaseCustomersController {
|
|||
// instead of overriding the whole method here.
|
||||
$customer = Customer::findOrFail($id);
|
||||
|
||||
// Get the list of Mailboxes the current User has access to.
|
||||
$mailboxes = auth()
|
||||
->user()
|
||||
->mailboxesCanView();
|
||||
|
||||
$customer_emails = $customer->emails;
|
||||
if (count($customer_emails)) {
|
||||
foreach ($customer_emails as $row) {
|
||||
|
@ -31,7 +36,11 @@ class CustomersController extends BaseCustomersController {
|
|||
$emails = [''];
|
||||
}
|
||||
|
||||
return view('customers/update', ['customer' => $customer, 'emails' => $emails]);
|
||||
return view('freescout-restricted-customers::customers/update', [
|
||||
'customer' => $customer,
|
||||
'mailboxes' => $mailboxes,
|
||||
'emails' => $emails,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -377,7 +386,7 @@ class CustomersController extends BaseCustomersController {
|
|||
|
||||
$response['status'] = 'success';
|
||||
|
||||
$response['html'] = view('customers/partials/customers_table', [
|
||||
$response['html'] = view('freescout-restricted-customers::customers/partials/customers_table', [
|
||||
'customers' => $customers,
|
||||
])->render();
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue