How to add custom ticket filter to your customer portal

This article explains how to define a custom ticket filter that will allow your customers to filter their tickets when they are viewing them in your Customer portal->My Tickets tab.
In the example below we use multiple conditions for filtering(text search, filter by ticket status, filter by ticket public tags, filter based on ticket creation date, ticket resolved date and ticket changed date). You don't need to use all of these filters if you don't want to, but you will need to adjust the example My tickets custom menu HTML code to match your exact needs. This implementation consists of few steps. We will need to define HTML code of the custom filter itself, then we will need to add some custom CSS to make it look better and also include some 3rd party scripts for the functionality.
 
Custom filter example below is designed to look the best in the Montana customer portal theme. If you are using different customer portal theme in your LiveAgent, you will need to adjust the CSS to match your actual customer portal design.

After you add the custom ticket filter, your customers/visitors will be able to find it on the "My tickets" tab in your LiveAgent customer portal. This tab is visible only for the logged in users. If you use the exact codes mentioned below, the final filter will look like this:

1. This is the actual custom filter HTML code that needs to be added to your LiveAgent. Open your LiveAgent admin panel, go to Customer portal tab->Settings->Configuration->Design->Own HTML->My tickets custom menu HTML. Don't forget to save the changes once you add the filter code.
<div class="panel panel-default margin-top margin-bottom">
    <div class="panel-heading">
      {if !isset($code) || $code == ""}
          Ticket Filters
      {elseif $code != ""}
         <a href="#" onclick="window.history.back();">Back to Ticket Filters</a>
      {/if}
  </div>
  {if !isset($code) || $code == ""}
    <div class="panel-body">
    <div class="filter-body">
        <div class="filter_label"></div>
            <input type="text" id="filterQuery" name="filterQuery"  value="{$query|escape}" placeholder="Search text" />
    </div>
    <div class="filter-body">
        <div class="filter_label">Status</div>
            <select class="status-select" name="status">
            <option value="A" {if $status == "A"}selected{/if}>Any</option>
            <option value="O" {if $status == "O"}selected{/if}>Open</option>
            <option value="AN" {if $status == "AN"}selected{/if}>Answered</option>
            <option value="RD" {if $status == "RD"}selected{/if}>Resolved</option>
            </select>
    </div>
    <div class="filter-body">
        <div class="filter_label">Tags</div>
            <select class="tags-select" name="tags[]" multiple="multiple">
                {foreach from=$publicTags item="tag" key="tag_id"}
            <option value="{$tag_id}" {if $selectedTags.$tag_id.name > ""}selected{/if} style="color:#{$tag.color}; background-color:#{$tag.backgroundcolor};">{$tag.name}</option>
                {/foreach}
            </select>
    </div>
    <div class="filter-body">
        <div class="filter_label">Created date</div>
        <div class="dateFilter input-group">
            <input id="createdFromInput" class="form-control" placeholder="from RRRR-MM-DD"  value="{$createdFrom}">
            <div id="createdFrom"></div>
            <div class="input-group-btn"><button id="createdFromToggle" class="btn btn-default glyphicon glyphicon-calendar"></button></div>
        </div>
        <div class="dateFilter input-group">
            <input id="createdToInput" class="form-control" placeholder="to RRRR-MM-DD" value="{$createdTo}">
            <div id="createdTo"></div>
            <div class="input-group-btn"><button id="createdToToggle" class="btn btn-default glyphicon glyphicon-calendar"></button></div>
        </div>
    </div>
    <div class="filter-body">
        <div class="filter_label">Changed date</div>
        <div class="dateFilter input-group">
            <input id="changedFromInput" class="form-control" placeholder="from RRRR-MM-DD">
            <div id="changedFrom"></div>
            <div class="input-group-btn"><button id="changedFromToggle" class="btn btn-default glyphicon glyphicon-calendar"></button></div>
        </div>
        <div class="dateFilter input-group">
            <input id="changedToInput" class="form-control" placeholder="to RRRR-MM-DD">
            <div id="changedTo"></div>
            <div class="input-group-btn"><button id="changedToToggle" class="btn btn-default glyphicon glyphicon-calendar"></button></div>
        </div>
    </div>

    <div class="filter-body">
        <div class="filter_label">Resolved date</div>
        <div class="dateFilter input-group">
            <input id="resolvedFromInput" class="form-control" placeholder="from RRRR-MM-DD">
            <div id="resolvedFrom"></div>
            <div class="input-group-btn"><button id="resolvedFromToggle" class="btn btn-default glyphicon glyphicon-calendar"></button></div>
        </div>
        <div class="dateFilter input-group">
            <input id="resolvedToInput" class="form-control" placeholder="to RRRR-MM-DD">
            <div id="resolvedTo"></div>
            <div class="input-group-btn"><button id="resolvedToToggle" class="btn btn-default glyphicon glyphicon-calendar"></button></div>
        </div>
    </div>

    <input type="button" value="Apply" class="btn btn-primary" onclick="submitFilter('{$myTicketsUrl}');" />
    <input type="button" value="Cancel" class="btn btn-default" onclick="clearFilter('{$myTicketsUrl}');" />
    </div>
<script>
{literal}
WindowDatePicker.createLanguage('en', {
    DAYS_ABBR: ['', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    MONTHS: ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    MONTHS_ABBR: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    AM_PM: ['AM', 'PM'],
    BUTTONS: ['Apply', 'Cancel'],
    INVALID_DATE: 'Invalid Date'
});
{/literal}
  const createdFrom = new
{literal}WindowDatePicker({{/literal}
    el: '#createdFrom',
    lang: 'en',
    toggleEl: '#createdFromToggle',
    inputEl: '#createdFromInput',
    value: '{$createdFrom}',
    type: 'DATE',
    dateType: 'YYYY-MM-DD',
{literal}});
  const createdTo = new WindowDatePicker({{/literal}
    el: '#createdTo',
    lang: 'en',
    toggleEl: '#createdToToggle',
    inputEl: '#createdToInput',
    value: '{$createdTo}',
    type: 'DATE',
    dateType: 'YYYY-MM-DD',
{literal}});{/literal}

  const changedFrom = new
{literal}WindowDatePicker({{/literal}
    el: '#changedFrom',
    lang: 'en',
    toggleEl: '#changedFromToggle',
    inputEl: '#changedFromInput',
    value: '{$changedFrom}',
    type: 'DATE',
    dateType: 'YYYY-MM-DD',
{literal}});
  const changedTo = new WindowDatePicker({{/literal}
    el: '#changedTo',
    lang: 'en',
    toggleEl: '#changedToToggle',
    inputEl: '#changedToInput',
    value: '{$changedTo}',
    type: 'DATE',
    dateType: 'YYYY-MM-DD',
{literal}});{/literal}

  const resolvedFrom = new
{literal}WindowDatePicker({{/literal}
    el: '#resolvedFrom',
    lang: 'en',
    toggleEl: '#resolvedFromToggle',
    inputEl: '#resolvedFromInput',
    value: '{$resolvedFrom}',
    type: 'DATE',
    dateType: 'YYYY-MM-DD',
{literal}});
  const resolvedTo = new WindowDatePicker({{/literal}
    el: '#resolvedTo',
    lang: 'en',
    toggleEl: '#resolvedToToggle',
    inputEl: '#resolvedToInput',
    value: '{$resolvedTo}',
    type: 'DATE',
    dateType: 'YYYY-MM-DD',
{literal}});{/literal}
</script>
  {/if}
</div>

2. Switch to Custom CSS tab(Customer portal tab->Settings->Configuration->Design->Custom CSS). Add this CSS and save the changes. Feel free to adjust the CSS to match your exact design needs.

.select2-container {width: auto !important; display:block !important;}
.select2-container > span {display:block !important;}


.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {color: inherit !important; font-size: 14px; line-height: 15px; vertical-align: bottom;}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {opacity:0.5}
.select2-container--default .select2-selection--multiple .select2-selection__choice {border-color:rgba(0,0,0,0.4) !important; float:none !important; font-size: 12px !important; text-overflow:ellipsis; overflow:hidden;}

.filter_label {
    color: #666;
    font-size: 12px;
}

.filter-body {
    margin-bottom: 10px;
}

#filterQuery {
    border-radius: 4px;
    border: 1px solid #aaa;
    padding: 12px 8px;
    width: 100%;
}

.select2-results__options li[aria-selected="true"] {display:none;}

.select2-results__option {
    border: 3px solid #fff;
    border-radius: 7px;
    font-size: 12px;
    line-height: 12px;
}

.select2-results__option:hover {
    opacity:0.8;
}


.dateFilter {
    margin-bottom:3px;
}

.dateFilter .input-group-btn:last-child > .btn,
.dateFilter .input-group-btn:last-child > .btn-group {
  margin-top:-2px;
}

.dateFilter input {
    width: 48%;
    font-size: 13px;
    padding: 9px 5px;
    margin: 0;
    display: inline-block;
}

.dateFilter .form-control {
  box-shadow:none;
}

.dateFilter button {
    margin: 0;
    display: inline-block;
}

.btn {height:auto;}

3. Switch to Tracking codes tab(Customer portal tab->Settings->Configuration->Tracking codes). We will add some necessary scripts and functions here.
    a) Add this code into the 

<link href="https://www.cssscript.com/demo/window-date-time-picker/dist/css/window-date-picker.css"  rel="stylesheet" type="text/css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/css/select2.min.css" rel="stylesheet" />
<script src="https://nostalgic-fermat-6932a4.netlify.com/window-date-picker.js"></script>

    b) Add this code into the 

<script src="https://nostalgic-fermat-6932a4.netlify.com/select2.js"></script>
<script type="text/javascript">
$(document).ready(function() {
    $('.tags-select').select2();
});
$(document).ready(function() {
    $('.status-select').select2();
});
function clearFilter(url) {
  window.location.href = url;
}
function submitFilter(url) {
    filterQuery = [];
    if ($('.tags-select').val() != [])  {
        filterQuery.push("t=" + $('.tags-select').val().join());
    }
    if ($('.status-select').val() != "")  {
        filterQuery.push("s=" + $('.status-select').val());
    }
    if ($('#createdFromInput').val() != "")  {
        filterQuery.push("created_from=" + $('#createdFromInput').val());
    }
    if ($('#createdToInput').val() != "")  {
        filterQuery.push("created_to=" + $('#createdToInput').val());
    }
    if ($('#changedFromInput').val() != "")  {
        filterQuery.push("changed_from=" + $('#changedFromInput').val());
    }
    if ($('#changedToInput').val() != "")  {
        filterQuery.push("changed_to=" + $('#changedToInput').val());
    }
    if ($('#resolvedFromInput').val() != "")  {
        filterQuery.push("resolved_from=" + $('#resolvedFromInput').val());
    }
    if ($('#resolvedToInput').val() != "")  {
        filterQuery.push("resolved_to=" + $('#resolvedToInput').val());
    }
    if ($('#filterQuery').val() != "")  {
        filterQuery.push("q=" + $('#filterQuery').val());
    }
    window.location.href = url + "?" + filterQuery.join("&");
}
</script>