Customers table view mode
This commit is contained in:
@@ -12,6 +12,7 @@ class EncryptCookies extends Middleware
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
'in_app'
|
||||
'in_app',
|
||||
'customers_view',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1794,6 +1794,18 @@ class Helper
|
||||
return (int)$request->cookie('in_app');
|
||||
}
|
||||
|
||||
/**
|
||||
* Customers list view mode: cards (default) or table.
|
||||
* The cookie is set from JS (see setCustomersView() in main.js).
|
||||
*/
|
||||
public static function getCustomersView($request = null)
|
||||
{
|
||||
if (!$request) {
|
||||
$request = app('request');
|
||||
}
|
||||
return $request->cookie('customers_view') == 'table' ? 'table' : 'cards';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get identifier for queue:work
|
||||
*/
|
||||
|
||||
79
public/css/style.css
vendored
79
public/css/style.css
vendored
@@ -3677,6 +3677,75 @@ ul.sidebar-block-list {
|
||||
.customers-pager a:hover {
|
||||
color: #333;
|
||||
}
|
||||
/* Customers list: table view */
|
||||
.customers-view-switch {
|
||||
color: #93a1af;
|
||||
cursor: pointer;
|
||||
margin-left: 6px;
|
||||
font-size: 13px;
|
||||
top: 2px;
|
||||
}
|
||||
.customers-view-switch:hover {
|
||||
color: #333;
|
||||
}
|
||||
.customers-table {
|
||||
background-color: #fff;
|
||||
/* Fixed layout: long values can not stretch the table, they are truncated. */
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
.customers-table-col-name {
|
||||
width: 34%;
|
||||
}
|
||||
.customers-table-col-email {
|
||||
width: 30%;
|
||||
}
|
||||
.customers-table-col-phone {
|
||||
width: 16%;
|
||||
}
|
||||
.customers-table-col-company {
|
||||
width: 20%;
|
||||
}
|
||||
.customers-table > thead > tr > th,
|
||||
.customers-table > tbody > tr > td {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.customers-table > thead > tr > th {
|
||||
color: #93a1af;
|
||||
font-weight: normal;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
.customers-table > tbody > tr > td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.customers-table-name > a {
|
||||
color: #2a3b47;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.customers-table-photo {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin-right: 6px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
@media (max-width:582px) {
|
||||
.customers-table > thead > tr > th:nth-child(n+3),
|
||||
.customers-table > tbody > tr > td:nth-child(n+3) {
|
||||
display: none;
|
||||
}
|
||||
.customers-table-col-name {
|
||||
width: 55%;
|
||||
}
|
||||
.customers-table-col-email {
|
||||
width: 45%;
|
||||
}
|
||||
}
|
||||
/*.customers-pager a:hover,
|
||||
.customers-pager a:active
|
||||
.customers-pager a:focus, {
|
||||
@@ -4195,6 +4264,16 @@ a.help-icon:hover {
|
||||
.text-larger {
|
||||
font-size: 16.8px;
|
||||
}
|
||||
.text-link,
|
||||
.text-link:focus {
|
||||
color: #0078D7!important;
|
||||
text-decoration: none!important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.text-link:hover {
|
||||
color: #000!important;
|
||||
text-decoration: none!important;
|
||||
}
|
||||
#loader-main {
|
||||
position: fixed;
|
||||
display: none;
|
||||
|
||||
39
public/js/main.js
vendored
39
public/js/main.js
vendored
@@ -2955,6 +2955,7 @@ function searchInit()
|
||||
starConversationInit();
|
||||
|
||||
customersPagination();
|
||||
customersViewSwitchInit();
|
||||
|
||||
$(".sidebar-menu .menu-link a").filter('[data-filter]').click(function(e){
|
||||
var trigger = $(this);
|
||||
@@ -3136,6 +3137,44 @@ function conversationPagination()
|
||||
});
|
||||
}
|
||||
|
||||
// Customers list view: cards (default) or table.
|
||||
// The choice is stored in the "customers_view" cookie and used by the server
|
||||
// when rendering the list (Helper::getCustomersView()).
|
||||
function setCustomersView(view)
|
||||
{
|
||||
view = (view == 'table') ? 'table' : 'cards';
|
||||
|
||||
// SameSite=Lax and no Secure flag, so the cookie works on HTTP installations too.
|
||||
setCookie('customers_view', view, {samesite: 'Lax'});
|
||||
updateCustomersViewSwitch(view);
|
||||
loadCustomers();
|
||||
}
|
||||
|
||||
function updateCustomersViewSwitch(view)
|
||||
{
|
||||
$('.customers-view-switch').each(function() {
|
||||
var button = $(this);
|
||||
var is_table = (view == 'table');
|
||||
var title = is_table ? button.attr('data-title-cards') : button.attr('data-title-table');
|
||||
|
||||
// Icon shows the view the user will switch to.
|
||||
button.toggleClass('glyphicon-th-large', is_table)
|
||||
.toggleClass('glyphicon-th-list', !is_table)
|
||||
.attr('title', title)
|
||||
.attr('data-original-title', title);
|
||||
});
|
||||
}
|
||||
|
||||
function customersViewSwitchInit()
|
||||
{
|
||||
$('.customers-view-switch').click(function(e) {
|
||||
setCustomersView(getCookie('customers_view') == 'table' ? 'cards' : 'table');
|
||||
// The switch is inside the tab link.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
function customersPagination()
|
||||
{
|
||||
$(".table-customers .pager-nav").click(function(e){
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
@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>
|
||||
<li @if ($mode == App\Conversation::SEARCH_MODE_CUSTOMERS)class="active"@endif><a href="@if ($mode == App\Conversation::SEARCH_MODE_CUSTOMERS)#@else{{ \Helper::fixProtocol(request()->fullUrlWithQuery(['mode' => App\Conversation::SEARCH_MODE_CUSTOMERS])) }}@endif">{{ __('Customers') }} <b>({{ $customers->total() }})</b>@if ($mode == App\Conversation::SEARCH_MODE_CUSTOMERS) <i class="text-link glyphicon @if (\Helper::getCustomersView() == 'table') glyphicon-th-large @else glyphicon-th-list @endif customers-view-switch" role="button" data-title-table="{{ __('Table View') }}" data-title-cards="{{ __('Cards View') }}" title="@if (\Helper::getCustomersView() == 'table'){{ __('Cards View') }}@else{{ __('Table View') }}@endif" data-toggle="tooltip"></i>@endif</a></li>
|
||||
</ul>
|
||||
@if ($mode == App\Conversation::SEARCH_MODE_CONV)
|
||||
@include('conversations/conversations_table', ['mailbox' => $search_mailbox, 'params' => ['target_blank' => false, 'show_mailbox' => (count(Auth::user()->mailboxesCanView(true)) > 1)]])
|
||||
|
||||
@@ -1,15 +1,40 @@
|
||||
@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() }}" />
|
||||
<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>
|
||||
@if (\Helper::getCustomersView() == 'table')
|
||||
<table class="table table-striped table-hover customers-table margin-top">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="customers-table-col-name">{{ __('Name') }}</th>
|
||||
<th class="customers-table-col-email">{{ __('Email') }}</th>
|
||||
<th class="customers-table-col-phone">{{ __('Phone') }}</th>
|
||||
<th class="customers-table-col-company">{{ __('Company') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($customers as $customer)
|
||||
<tr>
|
||||
<td class="customers-table-name">
|
||||
<a href="{{ Eventy::filter('customer.card.url', route('customers.update', ['id' => $customer->id]), $customer) }}" @action('customer.card.link', $customer) title="{{ $customer->first_name }} {{ $customer->last_name }}"><img src="{{ $customer->getPhotoUrl() }}" class="customers-table-photo" /> {{ $customer->first_name }} {{ $customer->last_name }}</a>
|
||||
</td>
|
||||
<td title="{{ $customer->getMainEmail() }}">{{ $customer->getMainEmail() }}</td>
|
||||
<td title="{{ $customer->getMainPhoneNumber() }}">{{ $customer->getMainPhoneNumber() }}</td>
|
||||
<td title="{{ $customer->company }}">{{ $customer->company }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@else
|
||||
<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() }}" />
|
||||
<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>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($customers->lastPage() > 1)
|
||||
|
||||
Reference in New Issue
Block a user