Selaa lähdekoodia

[search] Remove deprecated version

Romain Rigaux 11 vuotta sitten
vanhempi
commit
260e414a43

+ 2 - 2
README.rst

@@ -3,8 +3,8 @@
 Welcome to the repository for Hue
 =================================
 
-`Hue
-<http://gethue.com>`_ is an open source Web UI for doing big data with Hadoop.
+Hue is an open source Web interface for analyzing data with Apache Hadoop: `gethue.com
+<http://gethue.com>`_ 
 
 .. image:: docs/images/hue-screen.png
 

+ 1 - 4
apps/search/src/search/admin.py

@@ -15,9 +15,6 @@
 # limitations under the License.
 
 from django.contrib import admin
-from search.models import Collection, Result, Facet, Sorting
+from search.models import Collection
 
 admin.site.register(Collection)
-admin.site.register(Result)
-admin.site.register(Facet)
-admin.site.register(Sorting)

+ 0 - 80
apps/search/src/search/forms.py

@@ -14,83 +14,3 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-
-
-import math
-
-from django import forms
-from django.utils.translation import ugettext as _
-from search.models import Collection
-from search_controller import SearchController
-
-
-class QueryForm(forms.Form):
-  collection = forms.ChoiceField() # Aka collection_id
-
-  query = forms.CharField(label='', max_length=256, required=False, initial='',
-                          widget=forms.TextInput(attrs={'class': 'search-query input-xxlarge', 'data-bind': 'value: q'}))
-  fq = forms.CharField(label='', max_length=256, required=False, initial='', widget=forms.HiddenInput(), help_text='Solr Filter query')
-  sort = forms.CharField(label='', max_length=256, required=False, initial='', widget=forms.HiddenInput(), help_text='Solr sort')
-  rows = forms.CharField(label='', required=False, initial='', widget=forms.HiddenInput(), help_text='Solr records per page')
-  start = forms.CharField(label='', required=False, initial='', widget=forms.HiddenInput(), help_text='Solr start record')
-  facets = forms.CharField(label='', required=False, initial='', widget=forms.HiddenInput(), help_text='Show hide facet search')
-
-  def __init__(self, *args, **kwargs):
-    self.initial_collection = kwargs.pop('initial_collection')
-    super(QueryForm, self).__init__(*args, **kwargs)
-    choices = [(core.id, core.label) for core in Collection.objects.filter(enabled=True)]
-    # Beware: initial not working, set in the js
-    self.fields['collection'] = forms.ChoiceField(choices=choices, initial=self.initial_collection, required=False, label='', widget=forms.Select(attrs={'class':'hide'}))
-
-  def clean_collection(self):
-    if self.cleaned_data.get('collection'):
-      return self.cleaned_data['collection']
-    else:
-      return self.initial_collection
-
-  @property
-  def solr_query_dict(self):
-    solr_query = {}
-
-    if self.is_valid():
-      solr_query['q'] = self.cleaned_data['query'].encode('utf8')
-      solr_query['fq'] = self.cleaned_data['fq']
-      if self.cleaned_data['sort']:
-        solr_query['sort'] = self.cleaned_data['sort']
-      solr_query['rows'] = self.cleaned_data['rows'] or 15
-      solr_query['start'] = self.cleaned_data['start'] or 0
-      solr_query['facets'] = self.cleaned_data['facets'] or 1
-      solr_query['current_page'] = int(math.ceil((float(solr_query['start']) + 1) / float(solr_query['rows'])))
-      solr_query['total_pages'] = 0
-      solr_query['search_time'] = 0
-      solr_query['collection'] = Collection.objects.get(id=self.cleaned_data['collection']).name
-    
-    return solr_query
-
-
-class HighlightingForm(forms.Form):
-  fields = forms.MultipleChoiceField(required=False)
-  is_enabled = forms.BooleanField(label='Enabled', initial=True, required=False)
-
-  def __init__(self, *args, **kwargs):
-    fields = kwargs.pop('fields')
-    super(HighlightingForm, self).__init__(*args, **kwargs)
-    self.fields['fields'].choices = ((name, name) for name in fields)
-
-
-
-class CollectionForm(forms.ModelForm):
-  def __init__(self, *args, **kwargs):
-    self.user = kwargs.pop('user', None)
-    super(CollectionForm, self).__init__(*args, **kwargs)
-
-  class Meta:
-    model = Collection
-    exclude = ('facets', 'result', 'sorting', 'properties', 'cores')
-
-  def clean_name(self):
-    searcher = SearchController(self.user)
-    name = self.cleaned_data['name']
-    if not searcher.is_collection(name) and not searcher.is_core(name):
-      raise forms.ValidationError(_('No live Solr collection or core by the name %s.') % name)
-    return name

+ 27 - 188
apps/search/src/search/models.py

@@ -18,7 +18,6 @@
 import itertools
 import json
 import logging
-import math
 import numbers
 import re
 
@@ -36,6 +35,12 @@ from search.conf import SOLR_URL
 LOG = logging.getLogger(__name__)
 
 
+"""
+Collection manger contains all the data now.
+"""
+
+
+# Deprecated
 class Facet(models.Model):
   _ATTRIBUTES = ['properties', 'fields', 'ranges', 'dates', 'charts', 'order']
 
@@ -67,10 +72,6 @@ class Facet(models.Model):
       ('facet.sort', properties.get('sort')),
     )
 
-#    if data_dict.get('fields'):
-#      field_facets = tuple([('facet.field', field_facet['field']) for field_facet in data_dict['fields']])
-#      params += field_facets
-
     if data_dict.get('charts'):
       for field_facet in data_dict['charts']:
         if field_facet['start'] and field_facet['end'] and field_facet['gap']:
@@ -116,6 +117,7 @@ class Facet(models.Model):
     return params
 
 
+# Deprecated
 class Result(models.Model):
   _ATTRIBUTES = ['properties', 'template', 'highlighting', 'extracode']
 
@@ -167,6 +169,7 @@ class Result(models.Model):
     return params
 
 
+# Deprecated
 class Sorting(models.Model):
   _ATTRIBUTES = ['properties', 'fields']
 
@@ -251,6 +254,7 @@ class CollectionManager(models.Manager):
 
 
 class Collection(models.Model):
+  """All the data is now saved into the properties field"""
   enabled = models.BooleanField(default=True)
   name = models.CharField(max_length=40, verbose_name=_t('Solr index name pointing to'))
   label = models.CharField(max_length=100, verbose_name=_t('Friendlier name in UI'))
@@ -286,8 +290,6 @@ class Collection(models.Model):
       props['collection']['label'] = self.label
     if self.enabled is not None:
       props['collection']['enabled'] = self.enabled
-    # fields updated
-    # idField
     
     # tmp for dev    
     if 'rows' not in props['collection']['template']:
@@ -398,25 +400,6 @@ class Collection(models.Model):
     else:
       return '/search/static/art/icon_search_24.png'
 
-def get_facet_field_format(field, type, facets):
-  format = ""
-  try:
-    if type == 'field':
-      for fld in facets['fields']:
-        if fld['field'] == field:
-          format = fld['format']
-    elif type == 'range':
-      for fld in facets['ranges']:
-        if fld['field'] == field:
-          format = fld['format']
-    elif type == 'date':
-      for fld in facets['dates']:
-        if fld['field'] == field:
-          format = fld['format']
-  except:
-    pass
-  return format
-
 
 def get_facet_field(category, field, facets):
   facets = filter(lambda facet: facet['type'] == category and facet['field'] == field, facets)
@@ -425,64 +408,31 @@ def get_facet_field(category, field, facets):
   else:
     return None
 
+def pairwise2(cat, selected_values, iterable):
+  pairs = []
+  a, b = itertools.tee(iterable)
+  for element in a:
+    pairs.append({'cat': cat, 'value': element, 'count': next(a), 'selected': element in selected_values})
+  return pairs
+
+def range_pair(cat, selected_values, iterable, end):
+  # e.g. counts":["0",17430,"1000",1949,"2000",671,"3000",404,"4000",243,"5000",165],"gap":1000,"start":0,"end":6000}
+  pairs = []
+  a, to = itertools.tee(iterable)
+  next(to, None)
+  for element in a:
+    next(to, None)
+    to_value = next(to, end)
+    pairs.append({'field': cat, 'from': element, 'value': next(a), 'to': to_value, 'selected': element in selected_values})
+  return pairs
 
-def get_facet_field_label(field, facets):
-  label = field
 
-  facets = filter(lambda facet: facet['type'] == 'field' and facet['field'] == field, facets)
-  if facets:
-    return facets[0]['label']
-  else:
-    return label
-
-def get_facet_field_uuid(field, type, facets):
-  uuid = ''
-  if type == 'field':
-    for fld in facets['fields']:
-      if fld['field'] == field:
-        uuid = fld['uuid']
-  elif type == 'range':
-    for fld in facets['ranges']:
-      if fld['field'] == field:
-        uuid = fld['uuid']
-  elif type == 'date':
-    for fld in facets['dates']:
-      if fld['field'] == field:
-        uuid = fld['uuid']
-  return uuid
-
-def is_chart_field(field, charts):
-  found = False
-  for fld in charts:
-    if field == fld['field']:
-      found = True
-  return found
-
-
-def augment_solr_response2(response, collection, query):
+def augment_solr_response(response, collection, query):
   augmented = response
   augmented['normalized_facets'] = []
 
   normalized_facets = []
 
-  def pairwise2(cat, selected_values, iterable):
-    pairs = []
-    a, b = itertools.tee(iterable)
-    for element in a:
-      pairs.append({'cat': cat, 'value': element, 'count': next(a), 'selected': element in selected_values})
-    return pairs
-
-  def range_pair(cat, selected_values, iterable, end):
-    # e.g. counts":["0",17430,"1000",1949,"2000",671,"3000",404,"4000",243,"5000",165],"gap":1000,"start":0,"end":6000}
-    pairs = []
-    a, to = itertools.tee(iterable)
-    next(to, None)
-    for element in a:
-      next(to, None)
-      to_value = next(to, end)
-      pairs.append({'field': cat, 'from': element, 'value': next(a), 'to': to_value, 'selected': element in selected_values})
-    return pairs
-
   selected_values = dict([((fq['id'], fq['field'], fq['type']), fq['filter']) for fq in query['fqs']])
 
   if response and response.get('facet_counts'):
@@ -590,114 +540,3 @@ def augment_solr_exception(response, collection):
       ]
     }
   }) 
-
-def augment_solr_response(response, facets, solr_query):
-  augmented = response
-  augmented['normalized_facets'] = []
-
-  normalized_facets = {}
-  default_facets = []
-
-  chart_facets = facets.get('charts', [])
-
-  def pairwise(iterable):
-      "s -> (s0,s1), (s1,s2), (s2, s3), ..."
-      a, b = itertools.tee(iterable)
-      next(b, None)
-      return list(itertools.izip(a, b))
-
-  def pairwise2(cat, fq, iterable):
-      pairs = []
-      a, b = itertools.tee(iterable)
-      for element in a:
-        pairs.append({'cat': cat, 'value': element, 'count': next(a), 'selected': element == selected_field})
-      return pairs
-
-  fq = solr_query['fq']
-
-  if response and response.get('facet_counts'):
-    if response['facet_counts']['facet_fields']:
-      for cat in response['facet_counts']['facet_fields']:
-        selected_field = fq.get(cat, '')
-        facet = {
-          'field': cat,
-          'type': 'chart' if is_chart_field(cat, chart_facets) else 'field',
-          'label': get_facet_field_label(cat, is_chart_field(cat, chart_facets) and 'chart' or 'field', facets),
-          'counts': pairwise2(cat, selected_field, response['facet_counts']['facet_fields'][cat]),
-        }
-        uuid = get_facet_field_uuid(cat, 'field', facets)
-        if uuid == '':
-          default_facets.append(facet)
-        else:
-          normalized_facets[uuid] = facet
-
-    if response['facet_counts']['facet_ranges']:
-      for cat in response['facet_counts']['facet_ranges']:
-        facet = {
-          'field': cat,
-          'type': 'chart' if is_chart_field(cat, chart_facets) else 'range',
-          'label': get_facet_field_label(cat, 'range', facets),
-          'counts': response['facet_counts']['facet_ranges'][cat]['counts'],
-          'start': response['facet_counts']['facet_ranges'][cat]['start'],
-          'end': response['facet_counts']['facet_ranges'][cat]['end'],
-          'gap': response['facet_counts']['facet_ranges'][cat]['gap'],
-        }
-        uuid = get_facet_field_uuid(cat, 'range', facets)
-        if uuid == '':
-          default_facets.append(facet)
-        else:
-          normalized_facets[uuid] = facet
-
-    if response['facet_counts']['facet_dates']:
-      for cat in response['facet_counts']['facet_dates']:
-        facet = {
-          'field': cat,
-          'type': 'date',
-          'label': get_facet_field_label(cat, 'date', facets),
-          'format': get_facet_field_format(cat, 'date', facets),
-          'start': response['facet_counts']['facet_dates'][cat]['start'],
-          'end': response['facet_counts']['facet_dates'][cat]['end'],
-          'gap': response['facet_counts']['facet_dates'][cat]['gap'],
-        }
-        counts = []
-        for date, count in response['facet_counts']['facet_dates'][cat].iteritems():
-          if date not in ('start', 'end', 'gap'):
-            counts.append(date)
-            counts.append(count)
-        facet['counts'] = counts
-
-        uuid = get_facet_field_uuid(cat, 'date', facets)
-        if uuid == '':
-          default_facets.append(facet)
-        else:
-          normalized_facets[uuid] = facet
-
-    if response and response.get('response'):
-      
-      # Todo, and not as ugly as below, probably simplify to go back beginning + < >
-      
-      pages_to_show = 5 # always use an odd number since we do it symmetrically
-
-#      beginning = 0
-#      previous = int(solr_query["start"]) - int(solr_query["rows"])
-#      next = int(solr_query["start"]) + int(solr_query["rows"])
-#
-#      pages_after = (pages_to_show - 1) / 2
-#      pages_total = solr_query['total_pages']+1
-#      real_pages_after =  pages_total - solr_query["current_page"]
-#      symmetric_start = solr_query["current_page"] < pages_total - pages_after
-#      symmetric_end = solr_query["current_page"] > pages_after
-#
-#      pagination_start = solr_query["current_page"] > (pages_to_show - 1)/2 and (symmetric_start and solr_query["current_page"] - (pages_to_show - 1)/2 or solr_query["current_page"] - pages_to_show + real_pages_after ) or 1
-#      pagination_end = solr_query["current_page"] < solr_query['total_pages']+1-(pages_to_show - 1)/2 and (symmetric_end and solr_query["current_page"] + (pages_to_show - 1)/2 + 1 or solr_query["current_page"] + (pages_to_show - solr_query["current_page"]) + 1) or solr_query['total_pages']+1
-      
-
-  for ordered_uuid in facets.get('order', []):
-    try:
-      augmented['normalized_facets'].append(normalized_facets[ordered_uuid])
-    except:
-      pass
-  if default_facets:
-    augmented['normalized_facets'].extend(default_facets)
-
-  return augmented

+ 2 - 1
apps/search/src/search/settings.py

@@ -13,7 +13,8 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-DJANGO_APPS = [ "search" ]
+
+DJANGO_APPS = ["search"]
 NICE_NAME = "Solr Search"
 MENU_INDEX = 42
 ICON = "/search/static/art/icon_search_24.png"

+ 0 - 1072
apps/search/src/search/templates/admin_collection_facets.mako

@@ -1,1072 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-  from desktop.views import commonheader, commonfooter
-  from django.utils.translation import ugettext as _
-%>
-
-<%namespace name="layout" file="layout.mako" />
-<%namespace name="macros" file="macros.mako" />
-
-${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
-
-<%layout:skeleton>
-  <%def name="title()">
-    <h4>${ _('Facets for') } <strong>${ hue_collection.name }</strong></h4>
-  </%def>
-  <%def name="navigation()">
-    ${ layout.sidebar(hue_collection, 'facets') }
-  </%def>
-  <%def name="content()">
-
-    <link href="/static/ext/css/bootstrap-editable.css" rel="stylesheet">
-    <script src="/static/ext/js/bootstrap-editable.min.js"></script>
-    <script src="/static/js/ko.editable.js"></script>
-
-    <form method="POST" class="form-horizontal" data-bind="submit: submit">
-      <div class="well">
-      <div class="section">
-        <div class="alert alert-info">
-          <div class="pull-right" style="margin-top: 10px">
-            <label>
-              <input type='checkbox' data-bind="checked: properties().isEnabled" style="margin-top: -2px; margin-right: 4px"/> ${_('Enabled') }
-            </label>
-          </div>
-          <h3>${_('Facets')}</h3>
-          ${_('Facets provide an intuitive way to filter the results.')}
-          ${_('Different types of facets can be added on the following steps.')}
-          <strong>&nbsp;<span data-bind="visible: !properties().isEnabled()">${_('Facets are currently disabled.')}</span></strong>
-        </div>
-      </div>
-
-      <div id="facets" class="section">
-        <ul class="nav nav-pills">
-          <li class="active"><a href="#step1" class="step">${ _('Step 1: General') }</a></li>
-          <li><a href="#step2" class="step">${ _('Step 2: Field Facets') }</a></li>
-          <li><a href="#step3" class="step">${ _('Step 3: Range Facets') }</a></li>
-          <li><a href="#step4" class="step">${ _('Step 4: Date Facets') }</a></li>
-          <li><a href="#step5" class="step">${ _('Step 5: Graphical Facet') }</a></li>
-          <li><a href="#step6" class="step">${ _('Step 6: Facets Order') }</a></li>
-        </ul>
-
-        <div id="step1" class="stepDetails">
-          <div class="control-group">
-            <label class="control-label"> ${_('Limit') }</label>
-            <div class="controls">
-              <input type='number' data-bind="value: properties().limit" class="input-mini"/>
-            </div>
-          </div>
-          <div class="control-group">
-            <label class="control-label"> ${_('Mincount') }</label>
-            <div class="controls">
-              <input type='number' data-bind="value: properties().mincount" class="input-mini"/>
-            </div>
-          </div>
-          <div class="control-group">
-            <label class="control-label"> ${_('Sort') }</label>
-            <div class="controls">
-              <select data-bind="value: properties().sort">
-                <option value="count">count</option>
-                <option value="index">index</option>
-              </select>
-            </div>
-          </div>
-        </div>
-
-        <div id="step2" class="stepDetails hide">
-          <div data-bind="visible: fieldFacets().length == 0" style="padding-left: 10px;margin-bottom: 20px">
-            <em>${_('There are currently no field facets defined.')}</em>
-          </div>
-          <div data-bind="foreach: fieldFacets">
-            <div class="bubble">
-              <strong><span data-bind="editable: label"></span></strong>
-              <span style="color:#666;font-size: 12px">(<span data-bind="text: field"></span>)</span>
-              <a class="btn btn-small" data-bind="click: $root.removeFieldFacet"><i class="fa fa-trash-o"></i></a>
-            </div>
-          </div>
-          <div class="clearfix"></div>
-          <div class="miniform">
-            ${_('Field')}
-            <select id="select-field-facet" data-bind="options: fieldFacetsList, value: selectedFieldFacet"></select>
-            &nbsp;${_('Label')}
-            <input id="selectedFieldLabel" type="text" data-bind="value: selectedFieldLabel" class="input" />
-            <br/>
-            <br/>
-            <a class="btn" data-bind="click: $root.addFieldFacet"><i class="fa fa-plus-circle"></i> ${_('Add to Field Facets')}</a>
-            &nbsp;<span id="field-facet-error" class="label label-important hide">${_('The field you are trying to add is already in the list.')}</span>
-          </div>
-        </div>
-
-      <div id="step3" class="stepDetails hide">
-        <div data-bind="visible: rangeFacets().length == 0" style="padding-left: 10px;margin-bottom: 20px">
-          <em>${_('There are currently no range facets defined.')}</em>
-        </div>
-        <div data-bind="foreach: rangeFacets">
-          <div class="bubble">
-            <strong><span data-bind="editable: label"></span></strong>
-            <span style="color:#666;font-size: 12px">
-              (<span data-bind="text: field"></span>, <span data-bind="editable: start"></span> <i class="fa fa-double-angle-right"></i> <span data-bind="editable: end"></span>,
-              <i class="fa fa-resize-horizontal"></i> <span data-bind="editable: gap"></span>)
-            </span>
-            <a class="btn btn-small" data-bind="click: $root.removeRangeFacet"><i class="fa fa-trash-o"></i></a>
-          </div>
-        </div>
-        <div class="clearfix"></div>
-        <div class="miniform">
-          ${_('Field')}
-          <select data-bind="options: rangeFacetsList, value: selectedRangeFacet"></select>
-          &nbsp;${_('Label')}
-          <input id="selectedRangeLabel" type="text" data-bind="value: selectedRangeLabel" class="input" />
-          <br/>
-          <br/>
-          ${_('Start')}
-          <input type="number" data-bind="value: selectedRangeStartFacet" class="input-mini" />
-          &nbsp;${_('End')}
-          <input type="number" data-bind="value: selectedRangeEndFacet" class="input-mini" />
-          &nbsp;${_('Gap')}
-          <input type="number" data-bind="value: selectedRangeGapFacet" class="input-mini" />
-          <br/>
-          <br/>
-          <a class="btn" data-bind="click: $root.addRangeFacet"><i class="fa fa-plus-circle"></i> ${_('Add to Range Facets')}</a>
-        </div>
-      </div>
-
-      <div id="step4" class="stepDetails hide">
-        <div data-bind="visible: dateFacets().length == 0" style="padding-left: 10px;margin-bottom: 20px">
-          <em>${_('There are currently no date facets defined.')}</em>
-        </div>
-        <div data-bind="foreach: dateFacets">
-          <div class="bubble">
-            <strong><span data-bind="editable: label"></span></strong>
-            <span style="color:#666;font-size: 12px">
-              (<span data-bind="text: field"></span>, <span data-bind="editable: start"></span> <i class="fa fa-double-angle-right"></i> <span data-bind="editable: end"></span>,
-              <i class="fa fa-resize-horizontal"></i> <span data-bind="editable: gap"></span>, <i class="fa fa-calendar"></i> <span data-bind="editable: format"></span>)
-            </span>
-            <a class="btn btn-small" data-bind="click: $root.removeDateFacet"><i class="fa fa-trash-o"></i></a>
-          </div>
-        </div>
-        <div class="clearfix"></div>
-        <div class="miniform">
-          ${_('Field')}
-          <select data-bind="options: dateFacetsList, value: selectedDateFacet"></select>
-          &nbsp;${_('Label')}
-          <input id="selectedDateLabel" type="text" data-bind="value: selectedDateLabel" class="input" />
-          <br/>
-          <br/>
-          <span>
-            ${_('Range from')}
-            <span data-bind="template: {name: 'scriptDateMath', data: selectedDateDateMaths()[0]}"/>
-          </span>
-          <span>
-            &nbsp;${_('before today until')}
-            <span  data-bind="template: {name: 'scriptDateMath', data: selectedDateDateMaths()[1]}"/>
-          </span>
-          <span>
-            &nbsp;${_('before today. Goes up by increments of')}
-            <span id="scriptTable" data-bind="template: {name: 'scriptDateMath', data: selectedDateDateMaths()[2]}"/>
-          </span>
-          <br/>
-          <br/>
-          ${_('Date format')}
-          <input id="dateFormatInput" type="text" data-bind="value: selectedDateFormat" class="input" /> <a href="#formatHelpModal" class="btn btn-mini" data-toggle="modal"><i class="fa fa-question-circle"></i></a>
-          <br/>
-          <br/>
-          <a class="btn" data-bind="click: $root.addDateFacet"><i class="fa fa-plus-circle"></i> ${_('Add to Date Facets')}</a>
-        </div>
-      </div>
-
-      <div id="step5" class="stepDetails hide">
-        <div data-bind="visible: chartFacets().length == 0" style="padding-left: 10px;margin-bottom: 20px">
-          <em>${_('There is currently no graphical facet defined. Remember, you can add just one field as graphical facet.')}</em>
-        </div>
-        <div data-bind="foreach: chartFacets">
-          <div class="bubble">
-            <strong><span data-bind="editable: label"></span></strong>
-            <span style="color:#666;font-size: 12px">
-              (<span data-bind="text: field"></span>, <span data-bind="editable: start"></span> <i class="fa fa-double-angle-right"></i> <span data-bind="editable: end"></span>,
-              <i class="fa fa-resize-horizontal"></i> <span data-bind="editable: gap"></span>)
-            </span>
-            <a class="btn btn-small" data-bind="click: $root.removeChartFacet"><i class="fa fa-trash-o"></i></a>
-          </div>
-        </div>
-        <div class="clearfix"></div>
-        <div class="miniform">
-          ${_('Field')}
-          <select id="select-chart-facet" data-bind="options: chartFacetsList, value: selectedChartFacet"></select>
-          &nbsp;${_('Label')}
-          <input id="selectedChartLabel" type="text" data-bind="value: selectedChartLabel" class="input" />
-          <br/>
-          <br/>
-          ${_('Start')}
-          <input id="selectedChartStartFacet" type="text" data-bind="value: selectedChartStartFacet" class="input-mini" data-placeholder-general="${_('ie. 0')}" data-placeholder-date="${_('ie. NOW-12HOURS/MINUTES')}" />
-          &nbsp;${_('End')}
-          <input id="selectedChartEndFacet" type="text" data-bind="value: selectedChartEndFacet" class="input-mini" data-placeholder-general="${_('ie. 100')}" data-placeholder-date="${_('ie. NOW')}" />
-          &nbsp;${_('Gap')}
-          <input id="selectedChartGapFacet" type="text" data-bind="value: selectedChartGapFacet" class="input-mini" data-placeholder-general="${_('ie. 10')}" data-placeholder-date="${_('ie. +30MINUTES')}" />
-          <span class="muted">&nbsp;${_('If empty this will be treated as a simple Field Facet.')} &nbsp;<a href="http://wiki.apache.org/solr/SimpleFacetParameters#rangefaceting" target="_blank"><i class="fa fa-external-link"></i> ${_('Read more about facets...')}</a></span>
-          <br/>
-          <br/>
-          <a class="btn" data-bind="click: $root.addChartFacet, css:{disabled: $root.chartFacets().length == 1}"><i class="fa fa-plus-circle"></i> ${_('Set as Graphical Facet')}</a>
-          &nbsp;<span id="chart-facet-error" class="label label-important hide">${_('You can add just one field as graphical facet')}</span>
-          <span id="chart-facet-error-wrong-field-type" class="label label-important hide">${_('You can add just one field as graphical facet')}</span>
-        </div>
-      </div>
-
-      <div id="step6" class="stepDetails hide">
-        <div data-bind="visible: sortableFacets().length == 0" style="padding-left: 10px;margin-bottom: 20px">
-          <em>${_('There are currently no Facets defined.')}</em>
-        </div>
-        <div data-bind="sortable: sortableFacets, afterMove: isSaveBtnVisible(true)">
-          <div class="bubble" style="float: none;cursor: move">
-            <i class="fa fa-arrows"></i>
-            <strong><span data-bind="text: label"></span></strong>
-            <span style="color:#666;font-size: 12px">(<span data-bind="text: field"></span>)</span>
-          </div>
-        </div>
-      </div>
-
-      <script id="scriptDateMath" type="text/html">
-        <input class="input-mini" type="number" data-bind="value: frequency" />
-        <select class="input-small" data-bind="value: unit">
-          <option value="YEAR">YEARS</option>
-          <option value="MONTH">MONTHS</option>
-          <option value="DAYS">DAYS</option>
-          <option value="DATE">DATE</option>
-          <option value="HOURS">HOURS</option>
-          <option value="MINUTES">MINUTES</option>
-          <option value="SECONDS">SECONDS</option>
-          <option value="MILLISECONDS">MILLISECONDS</option>
-        </select>
-      </script>
-
-      </div>
-
-      <div class="form-actions" style="margin-top: 80px">
-        <a id="backBtn" class="btn disabled disable-feedback">${ _('Back') }</a>
-        <a id="nextBtn" class="btn btn-primary disable-feedback">${ _('Next') }</a>
-        <button type="submit" class="btn btn-primary" data-bind="visible: isSaveBtnVisible()" id="save-facets">${_('Save')}</button>
-      </div>
-    </div>
-    </form>
-  </%def>
-</%layout:skeleton>
-
-
-<div id="formatHelpModal" class="modal hide fade">
-  <div class="modal-header">
-    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-    <h3>${ _('Format Help') }</h3>
-  </div>
-  <div class="modal-body">
-    <p>
-      ${ _('You can specify here how you want the date to be formatted.')}
-      <br/>
-      ${ _('Use a predefined format:')}
-      <br/>
-      <table class="table table-striped table-bordered">
-      <tr>
-        <td>
-          <a href="javascript:void(0)" class="formatChooser">FROMNOW</a>
-        </td>
-      </tr>
-      <tr>
-        <td>
-          <a href="javascript:void(0)" class="formatChooser">YYYY/MM/DD</a>
-        </td>
-      </tr>
-      <tr>
-        <td>
-          <a href="javascript:void(0)" class="formatChooser">YYYY/MM/DD HH:mm</a>
-        </td>
-      </tr>
-      <tr>
-        <td>
-          <a href="javascript:void(0)" class="formatChooser">YYYY/MM/DD HH:mm:ss</a>
-        </td>
-      </tr>
-      <tr>
-        <td>
-          <a href="javascript:void(0)" class="formatChooser">HH:mm</a>
-        </td>
-      </tr>
-      <tr>
-        <td>
-          <a href="javascript:void(0)" class="formatChooser">HH:mm:ss</a>
-        </td>
-      </tr>
-    </table>
-    ${ _('or any combination of these fields:')} <br/><br/>
-
-    <table class="table table-striped table-bordered">
-  <tbody>
-    <tr>
-      <th></th>
-      <th>${ _('Token')}</th>
-      <th>${ _('Output')}</th>
-    </tr>
-    <tr>
-      <td><b>${ _('Relative time')}</b></td>
-      <td>FROMNOW</td>
-      <td>${_('9 hours ago')}</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Month')}</b></td>
-      <td>M</td>
-      <td>1 2 ... 11 12</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>Mo</td>
-      <td>1st 2nd ... 11th 12th</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>MM</td>
-      <td>01 02 ... 11 12</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>MMM</td>
-      <td>${ _('Jan Feb ... Nov Dec')}</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>MMMM</td>
-      <td>${ _('January February ... November December')}</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Day of Month')}</b></td>
-      <td>D</td>
-      <td>1 2 ... 30 30</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>Do</td>
-      <td>${ _('1st 2nd ... 30th 31st')}</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>DD</td>
-      <td>01 02 ... 30 31</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Day of Year')}</b></td>
-      <td>DDD</td>
-      <td>1 2 ... 364 365</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>DDDo</td>
-      <td>${ _('1st 2nd ... 364th 365th')}</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>DDDD</td>
-      <td>001 002 ... 364 365</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Day of Week')}</b></td>
-      <td>d</td>
-      <td>0 1 ... 5 6</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>do</td>
-      <td>${ _('0th 1st ... 5th 6th')}</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>ddd</td>
-      <td>${ _('Sun Mon ... Fri Sat')}</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>dddd</td>
-      <td>${ _('Sunday Monday ... Friday Saturday')}</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Week of Year')}</b></td>
-      <td>w</td>
-      <td>1 2 ... 52 53</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>wo</td>
-      <td>${ _('1st 2nd ... 52nd 53rd')}</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>ww</td>
-      <td>01 02 ... 52 53</td>
-    </tr>
-    <tr>
-      <td><b>${ _('ISO Week of Year')}</b></td>
-      <td>W</td>
-      <td>1 2 ... 52 53</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>Wo</td>
-      <td>${ _('1st 2nd ... 52nd 53rd')}</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>WW</td>
-      <td>01 02 ... 52 53</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Year')}</b></td>
-      <td>YY</td>
-      <td>70 71 ... 29 30</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>YYYY</td>
-      <td>1970 1971 ... 2029 2030</td>
-    </tr>
-    <tr>
-      <td><b>AM/PM</b></td>
-      <td>A</td>
-      <td>AM PM</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>a</td>
-      <td>am pm</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Hour')}</b></td>
-      <td>H</td>
-      <td>0 1 ... 22 23</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>HH</td>
-      <td>00 01 ... 22 23</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>h</td>
-      <td>1 2 ... 11 12</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>hh</td>
-      <td>01 02 ... 11 12</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Minute')}</b></td>
-      <td>m</td>
-      <td>0 1 ... 58 59</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>mm</td>
-      <td>00 01 ... 58 59</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Second')}</b></td>
-      <td>s</td>
-      <td>0 1 ... 58 59</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>ss</td>
-      <td>00 01 ... 58 59</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Fractional Second')}</b></td>
-      <td>S</td>
-      <td>0 1 ... 8 9</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>SS</td>
-      <td>0 1 ... 98 99</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>SSS</td>
-      <td>0 1 ... 998 999</td>
-    </tr>
-    <tr>
-      <td></td>
-      <td>ss</td>
-      <td>00 01 ... 58 59</td>
-    </tr>
-    <tr>
-      <td><b>${ _('Unix Timestamp')}</b></td>
-      <td>X</td>
-      <td>1360013296</td>
-    </tr>
-  </tbody>
-</table>
-    </p>
-  </div>
-  <div class="modal-footer">
-    <a href="javascript:void(0)" class="btn" data-dismiss="modal">${ _('Close')}</a>
-  </div>
-</div>
-
-<link rel="stylesheet" href="/static/ext/css/bootstrap-datepicker.min.css" type="text/css" media="screen" title="no title" charset="utf-8" />
-<link href="/static/ext/css/bootstrap-editable.css" rel="stylesheet">
-
-<script src="/static/ext/js/routie-0.3.0.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/bootstrap-datepicker.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/bootstrap-editable.min.js"></script>
-<script src="/static/ext/js/moment.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/knockout-sortable.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/jquery/plugins/jquery-ui-1.10.4.draggable-droppable-sortable.min.js"></script>
-
-<script type="text/javascript">
-  var MOMENT_DATE_FORMAT = "MM-DD-YYYY";
-
-  function s4() {
-    return Math.floor((1 + Math.random()) * 0x10000)
-            .toString(16)
-            .substring(1);
-  }
-
-  function UUID() {
-    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
-            s4() + '-' + s4() + s4() + s4();
-  }
-
-  var Facet = function (args) {
-    var _facet = {
-      uuid: (typeof args['uuid'] !== 'undefined' && args['uuid'] != null) ? args['uuid'] : UUID(),
-      type: args['type'],
-      field: args['field'],
-      label: ko.observable(args['label']),
-      format: ko.observable(args['format']),
-      start: ko.observable(args['start']),
-      end: ko.observable(args['end']),
-      gap: ko.observable(args['gap']),
-      isVerbatim: false,
-      verbatim: ""
-    }
-    _facet.label.subscribe(function (newValue) {
-      if ($.trim(newValue) == ""){
-        _facet.label(_facet.field);
-      }
-      viewModel.isSaveBtnVisible(true);
-    });
-    _facet.format.subscribe(function (newValue) {
-      viewModel.isSaveBtnVisible(true);
-    });
-    _facet.start.subscribe(function (newValue) {
-      if (_facet.type == "date" && typeof newValue == "string"){
-        valueParseHelper(newValue, _facet.start, 10);
-      }
-      viewModel.isSaveBtnVisible(true);
-    });
-    _facet.end.subscribe(function (newValue) {
-      if (_facet.type == "date" && typeof newValue == "string"){
-        valueParseHelper(newValue, _facet.end, 0);
-      }
-      viewModel.isSaveBtnVisible(true);
-    });
-    _facet.gap.subscribe(function (newValue) {
-      if (_facet.type == "date" && typeof newValue == "string"){
-        valueParseHelper(newValue, _facet.gap, 1);
-      }
-      viewModel.isSaveBtnVisible(true);
-    });
-    return _facet;
-  }
-
-  function valueParseHelper(value, field, defaultFrequency){
-    // try to parse the user free input
-    try {
-      field(new DateMath({frequency: parseFloat($.trim(value).split(" ")[0]), unit: $.trim(value).split(" ")[1]}));
-    }
-    catch (exception){
-      $(document).trigger("error", "${ _('There was an error parsing your input') }");
-      field(new DateMath({frequency: defaultFrequency, unit: 'DAYS'}));
-    }
-  }
-
-  var FieldFacet = function (obj) {
-    return new Facet({type: "field", field: obj.field, label: obj.label, uuid: obj.uuid});
-  }
-
-  var ChartFacet = function (obj) {
-    return new Facet({type: "chart", field: obj.field, label: obj.label, start: obj.start, end: obj.end, gap: obj.gap, uuid: obj.uuid});
-  }
-
-  var RangeFacet = function (obj) {
-    return new Facet({type: "range", field: obj.field, label: obj.label, start: obj.start, end: obj.end, gap: obj.gap, uuid: obj.uuid});
-  }
-
-  var DateFacet = function (obj) {
-    return new Facet({type: "date", field: obj.field, label: obj.label, format: obj.format, start: obj.start, end: obj.end, gap: obj.gap, uuid: obj.uuid});
-  }
-
-  var Properties = function (properties) {
-    var self = this;
-
-    self.isEnabled = ko.observable(properties.isEnabled);
-    self.limit = ko.observable(properties.limit);
-    self.mincount = ko.observable(properties.mincount);
-    self.sort = ko.observable(properties.sort);
-
-    self.isEnabled.subscribe(function (newValue) {
-      viewModel.isSaveBtnVisible(true);
-    });
-
-    self.limit.subscribe(function (newValue) {
-      viewModel.isSaveBtnVisible(true);
-    });
-
-    self.mincount.subscribe(function (newValue) {
-      viewModel.isSaveBtnVisible(true);
-    });
-
-    self.sort.subscribe(function (newValue) {
-      viewModel.isSaveBtnVisible(true);
-    });
-  }
-
-  var DateMath = function (args) {
-    var self = this;
-
-    self.frequency = ko.observable(args['frequency']);
-    self.unit = ko.observable(args['unit']);
-    self.isVerbatim = ko.observable(typeof args['isVerbatim'] !== 'undefined' ? args['isVerbatim'] : false);
-    self.verbatim = ko.observable(args['verbatim']);
-    self.isRounded = ko.observable(typeof args['isRounded'] !== 'undefined' ? args['isRounded'] : true);
-
-    self.toString = function() {
-      return self.frequency() + ' ' + self.unit();
-    };
-  }
-
-  function ViewModel() {
-    var self = this;
-
-    self.isSaveBtnVisible = ko.observable(false);
-
-    self.fields = ko.observableArray(${ hue_collection.fields(user) | n,unicode });
-
-    self.fullFields = {}
-    $.each(${ hue_collection.fields_data(user) | n,unicode }, function(index, field) {
-      self.fullFields[field.name] = field;
-    });
-
-    self.properties = ko.observable(new Properties(${ hue_collection.facets.data | n,unicode }.properties));
-
-    self.fieldFacets = ko.observableArray(ko.utils.arrayMap(${ hue_collection.facets.data | n,unicode }.fields, function (obj) {
-      return new FieldFacet(obj);
-    }));
-
-    // Remove already selected fields
-    self.fieldFacetsList = ko.observableArray(${ hue_collection.fields(user) | n,unicode });
-    $.each(self.fieldFacets(), function(index, field) {
-      self.fieldFacetsList.remove(field.field);
-    });
-
-    self.rangeFacets = ko.observableArray(ko.utils.arrayMap(${ hue_collection.facets.data | n,unicode }.ranges, function (obj) {
-      return new RangeFacet(obj);
-    }));
-
-    // Only ranges
-    self.rangeFacetsList = ko.observableArray([]);
-    $.each(self.fields(), function(index, field) {
-      if (self.fullFields[field] && ['tdate', 'date', 'tint', 'int', 'tlong', 'long', 'double', 'tdouble'].indexOf(self.fullFields[field].type) >= 0) {
-        self.rangeFacetsList.push(field);
-      }
-    });
-
-    self.dateFacets = ko.observableArray(ko.utils.arrayMap(${ hue_collection.facets.data | n,unicode }.dates, function (obj) {
-      return new DateFacet({
-          field: obj.field,
-          label: obj.label,
-          format: obj.format,
-          start: new DateMath(obj.start),
-          end: new DateMath(obj.end),
-          gap: new DateMath(obj.gap),
-          uuid: obj.uuid,
-      });
-    }));
-    // Only dates
-    self.dateFacetsList = ko.observableArray([]);
-    $.each(self.fields(), function(index, field) {
-      if (self.fullFields[field] && ['tdate', 'date'].indexOf(self.fullFields[field].type) >= 0) {
-        self.dateFacetsList.push(field);
-      }
-    });
-
-    self.chartFacets = ko.observableArray(ko.utils.arrayMap(${ hue_collection.facets.data | n,unicode }.charts, function (obj) {
-      return new ChartFacet(obj);
-    }));
-
-    // Only dates and numbers
-    self.chartFacetsList = ko.observableArray([]);
-    $.each(self.fields(), function(index, field) {
-      if (self.fullFields[field] && ['tdate', 'date', 'tint', 'int', 'tlong', 'long', 'double', 'tdouble'].indexOf(self.fullFields[field].type) >= 0) {
-        self.chartFacetsList.push(field);
-      }
-    });
-
-    // List of all facets sorted by UUID
-    self.sortableFacets = ko.observableArray(self.fieldFacets().concat(self.rangeFacets()).concat(self.dateFacets()));
-    self.sortableFacets.sort(function(left, right) {
-      var sorted_ids = ${ hue_collection.facets.data | n,unicode }.order;
-      return sorted_ids.indexOf(left.uuid) > sorted_ids.indexOf(right.uuid);
-    })
-
-    self.selectedFieldFacet = ko.observable();
-    self.selectedFieldFacet.subscribe(function (newValue) {
-      $("#selectedFieldLabel").prop("placeholder", newValue);
-    });
-    self.selectedFieldLabel = ko.observable("");
-
-    self.selectedRangeFacet = ko.observable();
-    self.selectedRangeFacet.subscribe(function (newValue) {
-      $("#selectedRangeLabel").prop("placeholder", newValue);
-    });
-    self.selectedRangeLabel = ko.observable("");
-    self.selectedRangeStartFacet = ko.observable(0);
-    self.selectedRangeEndFacet = ko.observable(100);
-    self.selectedRangeGapFacet = ko.observable(10);
-
-    self.selectedDateFacet = ko.observable();
-    self.selectedDateFacet.subscribe(function (newValue) {
-      $("#selectedDateLabel").prop("placeholder", newValue);
-    });
-    self.selectedDateLabel = ko.observable("");
-    self.selectedDateFormat = ko.observable("");
-
-    self.selectedDateDateMaths = ko.observableArray([
-        // Same as addDateFacet()
-        new DateMath({frequency: 10, unit: 'DAYS'}),
-        new DateMath({frequency: 0, unit: 'DAYS'}),
-        new DateMath({frequency: 1, unit: 'DAYS'})
-    ]);
-
-    self.selectedChartFacet = ko.observable();
-    self.selectedChartFacet.subscribe(function (newValue) {
-      var _field = self.fullFields[newValue];
-      if (_field.type == "tdate"){
-        $("#selectedChartStartFacet").attr("placeholder", $("#selectedChartStartFacet").data("placeholder-date")).removeClass("input-mini");
-        $("#selectedChartEndFacet").attr("placeholder", $("#selectedChartEndFacet").data("placeholder-date")).removeClass("input-mini");
-        $("#selectedChartGapFacet").attr("placeholder", $("#selectedChartGapFacet").data("placeholder-date")).removeClass("input-mini");
-      }
-      else {
-        $("#selectedChartStartFacet").attr("placeholder", $("#selectedChartStartFacet").data("placeholder-general")).addClass("input-mini");
-        $("#selectedChartEndFacet").attr("placeholder", $("#selectedChartEndFacet").data("placeholder-general")).addClass("input-mini");
-        $("#selectedChartGapFacet").attr("placeholder", $("#selectedChartGapFacet").data("placeholder-general")).addClass("input-mini");
-      }
-      $("#selectedChartLabel").prop("placeholder", newValue);
-    });
-    self.selectedChartLabel = ko.observable("");
-    self.selectedChartStartFacet = ko.observable("");
-    self.selectedChartEndFacet = ko.observable("");
-    self.selectedChartGapFacet = ko.observable("");
-
-
-    self.removeFieldFacet = function (facet) {
-      self.fieldFacets.remove(facet);
-      self.sortableFacets.remove(facet);
-      self.fieldFacetsList.push(facet.field);
-      self.fieldFacetsList.sort();
-      self.updateSortableFacets();
-      self.isSaveBtnVisible(true);
-    };
-
-    self.removeRangeFacet = function (facet) {
-      self.rangeFacets.remove(facet);
-      self.sortableFacets.remove(facet);
-      self.updateSortableFacets();
-      self.isSaveBtnVisible(true);
-    };
-
-    self.removeDateFacet = function (facet) {
-      self.dateFacets.remove(facet);
-      self.sortableFacets.remove(facet);
-      self.updateSortableFacets();
-      self.isSaveBtnVisible(true);
-    };
-
-    self.removeChartFacet = function (facet) {
-      self.chartFacets.remove(facet);
-      self.sortableFacets.remove(facet);
-      self.chartFacetsList.push(facet.field);
-      self.chartFacetsList.sort();
-      self.updateSortableFacets();
-      self.isSaveBtnVisible(true);
-    };
-
-    self.updateSortableFacets = function () {
-      self.isSaveBtnVisible(true);
-    };
-
-    self.addFieldFacet = function () {
-      var found = false;
-      ko.utils.arrayForEach(self.fieldFacets(), function(facet) {
-        if (facet.field == self.selectedFieldFacet()){
-          found = true;
-        }
-      });
-      if (!found){
-        if (self.selectedFieldLabel() == ""){
-          self.selectedFieldLabel(self.selectedFieldFacet());
-        }
-        var newFacet = new FieldFacet({field: self.selectedFieldFacet(), label: self.selectedFieldLabel()});
-        self.fieldFacets.push(newFacet);
-        self.sortableFacets.push(newFacet);
-        self.selectedFieldLabel("");
-        self.fieldFacetsList.remove(self.selectedFieldFacet());
-        self.properties().isEnabled(true);
-        self.updateSortableFacets();
-        self.isSaveBtnVisible(true);
-      }
-      else {
-        $("#field-facet-error").show();
-      }
-    };
-
-    self.addRangeFacet = function () {
-      if (self.selectedRangeLabel() == ""){
-        self.selectedRangeLabel(self.selectedRangeFacet());
-      }
-      var newFacet = new RangeFacet({
-          field: self.selectedRangeFacet(),
-          label: self.selectedRangeLabel(),
-          start: self.selectedRangeStartFacet(),
-          end: self.selectedRangeEndFacet(),
-          gap: self.selectedRangeGapFacet()
-       });
-      self.rangeFacets.push(newFacet);
-      self.sortableFacets.push(newFacet);
-      self.selectedRangeLabel("");
-      self.selectedRangeStartFacet(0);
-      self.selectedRangeEndFacet(100);
-      self.selectedRangeGapFacet(10);
-      self.properties().isEnabled(true);
-      self.updateSortableFacets();
-      self.isSaveBtnVisible(true);
-    };
-
-    self.addDateFacet = function () {
-      if (self.selectedDateLabel() == ""){
-        self.selectedDateLabel(self.selectedDateFacet());
-      }
-      var newFacet = new DateFacet({
-          field: self.selectedDateFacet(),
-          label: self.selectedDateLabel(),
-          format: self.selectedDateFormat(),
-          start: self.selectedDateDateMaths()[0],
-          end: self.selectedDateDateMaths()[1],
-          gap: self.selectedDateDateMaths()[2]
-      });
-      self.dateFacets.push(newFacet);
-      self.sortableFacets.push(newFacet);
-      self.selectedDateLabel("");
-      self.selectedDateFormat("");
-      self.selectedDateDateMaths([
-        new DateMath({frequency: 10, unit: 'DAYS'}),
-        new DateMath({frequency: 0, unit: 'DAYS'}),
-        new DateMath({frequency: 1, unit: 'DAYS'})
-      ]);
-      self.properties().isEnabled(true);
-      self.updateSortableFacets();
-      self.isSaveBtnVisible(true);
-    };
-
-
-    self.addChartFacet = function () {
-      if (self.chartFacets().length == 0){
-        var found = false;
-        ko.utils.arrayForEach(self.chartFacets(), function(facet) {
-          if (facet.field == self.selectedChartFacet()){
-            found = true;
-          }
-        });
-        if (!found){
-          if (self.selectedChartLabel() == ""){
-            self.selectedChartLabel(self.selectedChartFacet());
-          }
-          var newFacet = new ChartFacet({field: self.selectedChartFacet(), label: self.selectedChartLabel()});
-          var newFacet = new ChartFacet({
-            field: self.selectedChartFacet(),
-            label: self.selectedChartLabel(),
-            start: self.selectedChartStartFacet(),
-            end: self.selectedChartEndFacet(),
-            gap: self.selectedChartGapFacet()
-         });
-          self.chartFacets.push(newFacet);
-          self.selectedChartLabel("");
-          self.selectedChartStartFacet("");
-          self.selectedChartEndFacet("");
-          self.selectedChartGapFacet("");
-          self.chartFacetsList.remove(self.selectedChartFacet());
-          self.properties().isEnabled(true);
-          self.isSaveBtnVisible(true);
-        }
-      }
-      else {
-        $("#chart-facet-error").show();
-      }
-    };
-
-    self.submit = function () {
-      $.ajax("${ url('search:admin_collection_facets', collection_id=hue_collection.id) }", {
-        data: {
-          'properties': ko.toJSON(self.properties),
-          'fields': ko.toJSON(self.fieldFacets),
-          'ranges': ko.toJSON(self.rangeFacets),
-          'dates': ko.toJSON(self.dateFacets),
-          'charts': ko.toJSON(self.chartFacets),
-          'order': ko.toJSON(ko.utils.arrayMap(self.sortableFacets(), function (obj) {
-              return obj.uuid;
-           }))
-        },
-        contentType: 'application/json',
-        type: 'POST',
-        success: function () {
-          $(document).trigger("info", "${_('Facets updated')}");
-          self.isSaveBtnVisible(false);
-        },
-        error: function (data) {
-          $(document).trigger("error", "${_('Error: ')}" + data);
-        },
-        complete: function() {
-          $("#save-facets").button('reset');
-        }
-      });
-    };
-  };
-
-  var viewModel = new ViewModel();
-
-  $(document).ready(function () {
-    $(".btn-primary").button("reset");
-    ko.applyBindings(viewModel);
-    viewModel.isSaveBtnVisible(false);
-
-    $("#select-field-facet").click(function(){
-      $("#field-facet-error").hide();
-    });
-
-    $("#select-chart-facet").click(function(){
-      $("#chart-facet-error").hide();
-    });
-
-    var currentStep = "step1";
-
-    routie({
-      "step1":function () {
-        showStep("step1");
-      },
-      "step2":function () {
-        if (validateStep("step1")) {
-          showStep("step2");
-        }
-      },
-      "step3":function () {
-        if (validateStep("step1") && validateStep("step2")) {
-          showStep("step3");
-        }
-      },
-      "step4":function () {
-        if (validateStep("step1") && validateStep("step2")) {
-          showStep("step4");
-        }
-      },
-      "step5":function () {
-        if (validateStep("step1") && validateStep("step2")) {
-          showStep("step5");
-        }
-      },
-      "step6":function () {
-        if (validateStep("step1") && validateStep("step2")) {
-          showStep("step6");
-        }
-      }
-    });
-
-      function showStep(step) {
-        currentStep = step;
-        if (step != "step1") {
-          $("#backBtn").removeClass("disabled");
-        }
-        else {
-          $("#backBtn").addClass("disabled");
-        }
-        if (step != $(".stepDetails:last").attr("id")) {
-          $("#nextBtn").removeClass("disabled");
-        }
-        else {
-          $("#nextBtn").addClass("disabled");
-        }
-        $("a.step").parent().removeClass("active");
-        $("a.step[href=#" + step + "]").parent().addClass("active");
-        $(".stepDetails").hide();
-        $("#" + step).show();
-      }
-
-      function showSection(section) {
-        $(".section").hide();
-        $("#" + section).show();
-      }
-
-      function validateStep(step) {
-        var proceed = true;
-        $("#" + step).find("[validate=true]").each(function () {
-          if ($(this).val().trim() == "") {
-            proceed = false;
-            routie(step);
-            $(this).parents(".control-group").addClass("error");
-            $(this).parent().find(".help-inline").remove();
-            $(this).after("<span class=\"help-inline\"><strong>${ _('This field is required.') }</strong></span>");
-          }
-        });
-        return proceed;
-      }
-
-      $("#backBtn").click(function () {
-        var nextStep = (currentStep.substr(4) * 1 - 1);
-        if (nextStep >= 1) {
-          routie("step" + nextStep);
-        }
-      });
-
-      $("#nextBtn").click(function () {
-        var nextStep = (currentStep.substr(4) * 1 + 1);
-        if (nextStep <= $(".step").length) {
-          routie("step" + nextStep);
-        }
-      });
-
-      $(".formatChooser").on("click", function(){
-        viewModel.selectedDateFormat($(this).text());
-        $("#formatHelpModal").modal("hide");
-      });
-      var _typeSource = [];
-      $(".formatChooser").each(function(){
-        _typeSource.push($(this).text());
-      });
-
-      $("#dateFormatInput").typeahead({
-        source: _typeSource
-      });
-
-  });
-</script>
-
-${ commonfooter(messages) | n,unicode }

+ 0 - 151
apps/search/src/search/templates/admin_collection_highlighting.mako

@@ -1,151 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-  from desktop.views import commonheader, commonfooter
-  from django.utils.translation import ugettext as _
-%>
-
-<%namespace name="layout" file="layout.mako" />
-<%namespace name="macros" file="macros.mako" />
-
-${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
-
-<%layout:skeleton>
-  <%def name="title()">
-    <h4>${ _('Highlighting for') } <strong>${ hue_collection.name }</strong></h4>
-  </%def>
-
-  <%def name="navigation()">
-    ${ layout.sidebar(hue_collection, 'highlighting') }
-  </%def>
-
-  <%def name="content()">
-    <form method="POST" class="form" data-bind="submit: submit">
-      <div class="well">
-      <div class="section">
-        <div class="alert alert-info">
-          <div class="pull-right" style="margin-top: 10px">
-            <label>
-              <input type='checkbox' data-bind="checked: isEnabled" style="margin-top: -2px; margin-right: 4px"/> ${_('Enabled') }
-            </label>
-          </div>
-          <h3>${_('Highlighting')}</h3>
-          ${_('Highlights the query keywords matching some of the fields below.')}
-          <strong>
-            <span data-bind="visible: ! isEnabled()">
-            ${_('Highlighting is currently disabled.')}
-            </span>
-          </strong>
-        </div>
-        <div class="selector">
-          <select data-bind="options: fields, selectedOptions: highlightedFields" size="20" multiple="true" class="hide"></select>
-          <select id="fields" size="20" multiple="true"></select>
-        </div>
-      </div>
-
-      <div class="form-actions" style="margin-top: 80px">
-        <button type="submit" class="btn btn-primary" id="save-btn">${_('Save')}</button>
-      </div>
-      </div>
-    </form>
-  </%def>
-</%layout:skeleton>
-
-<style type="text/css">
-  #fields {
-    list-style-type: none;
-    margin: 0;
-    padding: 0;
-    width: 100%;
-  }
-
-  #fields li {
-    margin-bottom: 10px;
-    padding: 10px;
-    border: 1px solid #E3E3E3;
-    height: 30px;
-  }
-
-  .placeholder {
-    height: 30px;
-    background-color: #F5F5F5;
-    border: 1px solid #E3E3E3;
-  }
-</style>
-
-
-<script src="/static/ext/js/jquery/plugins/jquery-ui-1.10.4.draggable-droppable-sortable.min.js"></script>
-<script src="/static/js/jquery.selector.js"></script>
-
-<script type="text/javascript">
-  function ViewModel() {
-    var self = this;
-    self.fields = ko.observableArray(${ hue_collection.fields(user) | n,unicode });
-
-    var highlighting = ${ hue_collection.result.get_highlighting() | n,unicode };
-    var properties = ${ hue_collection.result.get_properties() | n,unicode };
-
-    self.highlightedFields = ko.observableArray(highlighting != null ? highlighting : []);
-    self.isEnabled = ko.observable(properties.highlighting_enabled);
-
-    self.submit = function () {
-      $.ajax("${ url('search:admin_collection_highlighting', collection_id=hue_collection.id) }", {
-        data: {
-          'properties': ko.utils.stringifyJson({'highlighting_enabled': self.isEnabled()}),
-          'highlighting': ko.utils.stringifyJson(self.highlightedFields)
-        },
-        contentType: 'application/json',
-        type: 'POST',
-        success: function () {
-          $(document).trigger("info", "${_('Updated')}");
-        },
-        error: function (data) {
-          $(document).trigger("error", "${_('Error: ')}" + data);
-        },
-        complete: function() {
-          $("#save-btn").button('reset');
-        }
-      });
-    };
-  };
-
-  var viewModel = new ViewModel();
-
-  $(document).ready(function () {
-    ko.applyBindings(viewModel);
-
-    ko.utils.arrayForEach(viewModel.fields(), function(field) {
-      $("<option>").attr("value", field).text(field).appendTo($("#fields"));
-    });
-
-    $("#fields").val(viewModel.highlightedFields());
-
-    $("#fields").jHueSelector({
-      selectAllLabel: "${_('Select all')}",
-      searchPlaceholder: "${_('Search')}",
-      noChoicesFound: "${_('No fields found.')}",
-      width:$(".selector").width(),
-      height:340,
-      onChange: function(){
-        viewModel.highlightedFields($("#fields").val());
-        viewModel.isEnabled(viewModel.highlightedFields() != null);
-      }
-    });
-  });
-</script>
-
-${ commonfooter(messages) | n,unicode }

+ 0 - 154
apps/search/src/search/templates/admin_collection_properties.mako

@@ -1,154 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-  from desktop.views import commonheader, commonfooter
-  from django.utils.translation import ugettext as _
-%>
-
-<%namespace name="layout" file="layout.mako" />
-<%namespace name="macros" file="macros.mako" />
-<%namespace name="utils" file="utils.inc.mako" />
-
-
-${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
-
-<%def name="indexProperty(key)">
-  %if key in solr_collection["status"][hue_collection.name]["index"]:
-      ${ solr_collection["status"][hue_collection.name]["index"][key] }
-    %endif
-</%def>
-
-<%def name="collectionProperty(key)">
-  %if key in solr_collection["status"][hue_collection.name]:
-      ${ solr_collection["status"][hue_collection.name][key] }
-    %endif
-</%def>
-
-<%layout:skeleton>
-  <%def name="title()">
-    <h4>${ _('Properties of') } <strong>${ hue_collection.name }</strong></h4>
-  </%def>
-
-  <%def name="navigation()">
-    ${ layout.sidebar(hue_collection, 'properties') }
-  </%def>
-
-  <%def name="content()">
-  <form id="collectionProperties" method="POST">
-    <ul class="nav nav-tabs" style="margin-bottom:0; margin-top:10px">
-      <li class="active">
-        <a href="#index" data-toggle="tab">${_('Collection')}</a>
-      </li>
-      <li>
-        <a href="#schema" data-toggle="tab">${_('Schema')}</a>
-      </li>
-      <li>
-        <a href="#properties" data-toggle="tab">${_('Indexes')}</a>
-      </li>
-    </ul>
-    <div class="well">
-    <div class="tab-content">
-      <div class="tab-pane active" id="index">
-        <div class="fieldWrapper">
-          ${ utils.render_field(collection_form['enabled']) }
-          ${ utils.render_field(collection_form['label']) }
-          ${ utils.render_field(collection_form['name']) }
-
-          ${ _('Autocomplete and suggest queries') } <br/> <input type="checkbox" data-bind="checked: autocomplete" />
-        </div>
-
-      <div class="form-actions">
-        <a class="btn btn-primary" id="saveBtn">${_('Save')}</a>
-      </div>
-      </div>
-
-      <div class="tab-pane" id="schema">
-        <textarea id="schema_field">${_('Loading...')}</textarea>
-      </div>
-
-      <div class="tab-pane" id="properties">
-        ${_('Loading...')} <img src="/static/art/spinner.gif">
-      </div>
-    </div>
-    </div>
-  </form>
-  </%def>
-
-</%layout:skeleton>
-
-<script src="/static/ext/js/codemirror-3.11.js"></script>
-<link rel="stylesheet" href="/static/ext/css/codemirror.css">
-<script src="/static/ext/js/codemirror-xml.js"></script>
-
-
-<script src="/static/ext/js/knockout.mapping-2.3.2.js" type="text/javascript" charset="utf-8"></script>
-
-<script type="text/javascript" charset="utf-8">
-  $(document).ready(function(){
-    var schemaViewer = $("#schema_field")[0];
-
-    var codeMirror = CodeMirror(function (elt) {
-        schemaViewer.parentNode.replaceChild(elt, schemaViewer);
-      }, {
-        value: schemaViewer.value,
-        readOnly: true,
-        lineNumbers: true
-    });
-
-    var ViewModel = function() {
-        var self = this;
-        self.autocomplete = ko.observable(${ collection_properties | n }.autocomplete);
-
-        self.submit = function(form) {
-          var form = $("#collectionProperties");
-
-          $("<input>").attr("type", "hidden")
-                  .attr("name", "autocomplete")
-                  .attr("value", ko.utils.stringifyJson(self.autocomplete))
-                  .appendTo(form);
-
-          form.submit();
-        };
-      };
-
-    window.viewModel = new ViewModel();
-    ko.applyBindings(window.viewModel, $('#collectionProperties')[0]);
-
-
-    $("#saveBtn").click(function () {
-      window.viewModel.submit();
-    });
-
-    codeMirror.setSize("100%", $(document).height() - 150 - $(".form-actions").outerHeight());
-
-    $.get("${ url('search:admin_collection_schema', collection_id=hue_collection.id) }", function (data) {
-      codeMirror.setValue(data.solr_schema);
-    });
-    $.get("${ url('search:admin_collection_solr_properties', collection_id=hue_collection.id) }", function (data) {
-      $("#properties").html(data.content);
-    });
-
-    // Force refresh on tab change
-    $("a[data-toggle='tab']").on("shown", function (e) {
-      if ($(e.target).attr("href") == "#schema") {
-        codeMirror.refresh();
-      }
-    });
- });
-</script>
-
-${ commonfooter(messages) | n,unicode }

+ 0 - 44
apps/search/src/search/templates/admin_collection_properties_solr_properties.mako

@@ -1,44 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-  from django.utils.translation import ugettext as _
-%>
-
-<%namespace name="layout" file="layout.mako" />
-<%namespace name="macros" file="macros.mako" />
-
-
-<div class="tab-content">
-  <div class="tab-pane active" id="index_properties">
-    <table class="table">
-      <thead>
-      <tr>
-        <th width="20%">${_('Property')}</th>
-        <th>${_('Value')}</th>
-      </tr>
-      </thead>
-      <tbody>
-      <tr>
-        % for key, value in solr_collection.iteritems():
-          <td>${ key }</td>
-          <td>${ value }</td>
-        % endfor
-      </tr>
-      </tbody>
-    </table>
-  </div>
-</div>

+ 0 - 235
apps/search/src/search/templates/admin_collection_sorting.mako

@@ -1,235 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-  from desktop.views import commonheader, commonfooter
-  from django.utils.translation import ugettext as _
-%>
-
-<%namespace name="layout" file="layout.mako" />
-<%namespace name="macros" file="macros.mako" />
-
-${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
-
-<%layout:skeleton>
-  <%def name="title()">
-    <h4>${ _('Sorting for') } <strong>${ hue_collection.name }</strong></h4>
-  </%def>
-
-  <%def name="navigation()">
-    ${ layout.sidebar(hue_collection, 'sorting') }
-  </%def>
-
-  <%def name="content()">
-
-    <link href="/static/ext/css/bootstrap-editable.css" rel="stylesheet">
-    <script src="/static/ext/js/bootstrap-editable.min.js"></script>
-    <script src="/static/js/ko.editable.js"></script>
-
-    <form method="POST" class="form-horizontal" data-bind="submit: submit">
-      <div class="well">
-      <div class="section">
-        <div class="alert alert-info">
-          <div class="pull-right" style="margin-top: 10px">
-            <label>
-              <input type='checkbox' data-bind="checked: isEnabled" style="margin-top: -2px; margin-right: 4px"/> ${_('Enabled') }
-            </label>
-          </div>
-          <h3>${_('Sorting')}</h3>
-          ${_('Specify on which fields and order the results are sorted by default.')}
-          ${_('The sorting is a combination of the "Default sorting" fields, from left to right.')}
-          <span data-bind="visible: ! isEnabled()"><strong>${_('Sorting is currently disabled.')}</strong></span>
-        </div>
-      </div>
-
-      <div class="section" style="padding: 5px">
-        <div data-bind="visible: sortingFields().length == 0" style="padding-left: 10px;margin-bottom: 20px">
-          <em>${_('There are currently no fields defined.')}</em>
-        </div>
-        <div data-bind="sortable: sortingFields">
-          <div class="bubble" style="cursor: move">
-            <i class="fa fa-arrows"></i>
-            <strong><span data-bind="editable: label"></span></strong>
-            <span style="color:#666;font-size: 12px">
-              (<span data-bind="text: field"></span> <i class="fa fa-arrow-up" data-bind="visible: asc() == true"></i><i class="fa fa-arrow-down" data-bind="visible: asc() == false"></i> <span data-bind="editable: order"></span>, <input type="checkbox" data-bind="checked: include" style="margin-top:0" /> ${_('Default sorting')} )
-            </span>
-            <a class="btn btn-small" data-bind="click: $root.removeSortingField"><i class="fa fa-trash-o"></i></a>
-          </div>
-        </div>
-        <div class="clearfix"></div>
-        <div class="miniform">
-          ${_('Field')}
-          <select data-bind="options: sortingFieldsList, value: newFieldSelect"></select>
-          &nbsp;${_('Label')}
-          <input id="newFieldLabel" type="text" data-bind="value: newFieldLabel" class="input" />
-          &nbsp;${_('Sorting')}
-          <div class="btn-group" style="display: inline">
-            <button id="newFieldAsc" type="button" data-bind="css: {'active': newFieldAscDesc() == 'asc', 'btn': true}"><i class="fa fa-arrow-up"></i></button>
-            <button id="newFieldDesc" type="button" data-bind="css: {'active': newFieldAscDesc() == 'desc', 'btn': true}"><i class="fa fa-arrow-down"></i></button>
-          </div>
-          <label class="checkbox" style="display: inline">
-            <input id="newFieldInclude" type="checkbox" style="float:none;margin-left:0;margin-top: -2px;margin-right: 4px"  data-bind="checked: newFieldIncludeInSorting" /> ${_('Include in default sorting')}
-          </label>
-          <br/>
-          <br/>
-          <a class="btn" data-bind="click: $root.addSortingField"><i class="fa fa-plus-circle"></i> ${_('Add to Sorting')}</a>
-        </div>
-      </div>
-
-      <div class="form-actions" style="margin-top: 80px">
-        <button type="submit" class="btn btn-primary" id="save-sorting">${_('Save')}</button>
-      </div>
-      </div>
-    </form>
-  </%def>
-</%layout:skeleton>
-
-<style type="text/css">
-  #fields {
-    list-style-type: none;
-    margin: 0;
-    padding: 0;
-    width: 100%;
-  }
-
-  #fields li {
-    margin-bottom: 10px;
-    padding: 10px;
-    border: 1px solid #E3E3E3;
-    height: 30px;
-  }
-
-  .placeholder {
-    height: 30px;
-    background-color: #F5F5F5;
-    border: 1px solid #E3E3E3;
-  }
-</style>
-
-<script src="/static/ext/js/knockout-sortable.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/jquery/plugins/jquery-ui-1.10.4.draggable-droppable-sortable.min.js"></script>
-
-<script type="text/javascript">
-
-  var SortingField = function (field, label, asc, include) {
-    var _field = {
-      field: field,
-      label: ko.observable(label),
-      asc: ko.observable(asc),
-      order: ko.observable(asc ? "ASC" : "DESC"),
-      include: ko.observable(include)
-    };
-    _field.label.subscribe(function (newValue) {
-      if ($.trim(newValue) == "") {
-        _field.label(f.field);
-      }
-    });
-    _field.order.subscribe(function (newValue) {
-      if ($.trim(newValue).toUpperCase() == "DESC") {
-        _field.asc(false);
-      }
-      else {
-        _field.asc(true);
-      }
-    });
-
-    return _field;
-  }
-
-  function ViewModel() {
-    var self = this;
-    self.fields = ko.observableArray(${ hue_collection.fields(user) | n,unicode });
-
-    self.isEnabled = ko.observable(${ hue_collection.sorting.data | n,unicode }.properties.is_enabled);
-
-    self.sortingFields = ko.observableArray(ko.utils.arrayMap(${ hue_collection.sorting.data | n,unicode }.fields, function (obj) {
-      return new SortingField(obj.field, obj.label, obj.asc, obj.include);
-    }));
-
-    var _cleanedFields = ko.utils.arrayFilter(${ hue_collection.fields_data(user) | n,unicode }, function (fieldObj) {
-      return fieldObj.type != "multiValued";
-    });
-
-    self.sortingFieldsList = ko.observableArray(ko.utils.arrayMap(_cleanedFields, function (fieldObj) {
-      return fieldObj.name;
-    }));
-
-    self.newFieldSelect = ko.observable();
-    self.newFieldSelect.subscribe(function (newValue) {
-      $("#newFieldLabel").prop("placeholder", newValue);
-    });
-
-    self.newFieldLabel = ko.observable("");
-    self.newFieldAscDesc = ko.observable("asc");
-
-    self.newFieldIncludeInSorting = ko.observable(true);
-
-    self.removeSortingField = function (field) {
-      self.sortingFields.remove(field);
-      self.sortingFieldsList.sort();
-      if (self.sortingFields().length == 0) {
-        self.isEnabled(false);
-      }
-    };
-
-    self.addSortingField = function () {
-      if (self.newFieldLabel() == ""){
-        self.newFieldLabel(self.newFieldSelect());
-      }
-      self.sortingFields.push(new SortingField(self.newFieldSelect(), self.newFieldLabel(), self.newFieldAscDesc() == "asc", self.newFieldIncludeInSorting()));
-      self.newFieldLabel("");
-      self.newFieldAscDesc("asc");
-      self.newFieldIncludeInSorting(true);
-      self.isEnabled(true);
-    };
-
-    self.submit = function () {
-      $.ajax("${ url('search:admin_collection_sorting', collection_id=hue_collection.id) }", {
-        data: {
-          'properties': ko.toJSON({'is_enabled': self.isEnabled()}),
-          'fields': ko.toJSON(self.sortingFields)
-        },
-        contentType: 'application/json',
-        type: 'POST',
-        success: function () {
-          $(document).trigger("info", "${_('Sorting updated')}");
-        },
-        error: function (data) {
-          $(document).trigger("error", "${_('Error: ')}" + data);
-        },
-        complete: function() {
-          $("#save-sorting").button('reset');
-        }
-      });
-    };
-  };
-
-  var viewModel = new ViewModel();
-
-  $(document).ready(function () {
-    ko.applyBindings(viewModel);
-
-    $("#newFieldAsc").click(function(){
-      viewModel.newFieldAscDesc("asc");
-    });
-
-    $("#newFieldDesc").click(function(){
-      viewModel.newFieldAscDesc("desc");
-    });
-  });
-</script>
-
-${ commonfooter(messages) | n,unicode }

+ 0 - 702
apps/search/src/search/templates/admin_collection_template.mako

@@ -1,702 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-  from desktop.views import commonheader, commonfooter
-  from django.utils.translation import ugettext as _
-%>
-
-<%namespace name="layout" file="layout.mako" />
-<%namespace name="macros" file="macros.mako" />
-
-${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
-
-<style type="text/css">
-  .CodeMirror {
-    border: 1px dotted #DDDDDD;
-  }
-
-  #content-editor {
-    outline: 0;
-    margin-top: 20px;
-    min-height: 400px;
-  }
-
-  #content-editor [class*="span"], .tmpl [class*="span"] {
-    background-color: #eee;
-    -webkit-border-radius: 3px;
-    -moz-border-radius: 3px;
-    border-radius: 3px;
-    min-height: 40px;
-    line-height: 40px;
-    background-color: #F3F3F3;
-    border: 2px dashed #DDD;
-  }
-
-  .tmpl {
-    margin: 10px;
-    height: 60px;
-  }
-
-  .tmpl [class*="span"] {
-    color: #999;
-    font-size: 12px;
-    text-align: center;
-    font-weight: bold;
-  }
-
-  .preview-row:nth-child(odd) {
-    background-color: #f9f9f9;
-  }
-
-  .widget-box {
-    background: none repeat scroll 0 0 #F9F9F9;
-    border-top: 1px solid #CDCDCD;
-    border-left: 1px solid #CDCDCD;
-    border-right: 1px solid #CDCDCD;
-    clear: both;
-    margin-top: 10px;
-    margin-bottom: 16px;
-    position: relative;
-    min-width: 260px;
-  }
-
-  .widget-title {
-    background-color: #efefef;
-    background-image: -webkit-gradient(linear, 0 0%, 0 100%, from(#fdfdfd), to(#eaeaea));
-    background-image: -webkit-linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
-    background-image: -moz-linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
-    background-image: -ms-linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
-    background-image: -o-linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
-    background-image: -linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
-    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdfdfd', endColorstr='#eaeaea', GradientType=0); /* IE6-9 */
-    border-bottom: 1px solid #CDCDCD;
-    height: 36px;
-  }
-
-  .widget-title span.icon {
-    border-right: 1px solid #cdcdcd;
-    padding: 9px 10px 7px 11px;
-    float: left;
-    opacity: .7;
-  }
-
-  .widget-title h5 {
-    color: #666666;
-    text-shadow: 0 1px 0 #ffffff;
-    float: left;
-    font-size: 12px;
-    font-weight: bold;
-    padding: 12px;
-    line-height: 12px;
-    margin: 0;
-  }
-
-  .widget-content {
-    padding: 12px 8px;
-    border-bottom: 1px solid #cdcdcd;
-  }
-
-  .carousel-control {
-    top: 100%;
-    outline: none;
-  }
-  .carousel-control:focus {
-    outline: none;
-  }
-
-  .tab-content {
-    overflow: inherit;
-  }
-
-  .chosen-container, .chosen-select {
-    float: left;
-  }
-
-  .plus-btn {
-    float: left;
-    height: 25px;
-    line-height: 15px!important;
-    margin-left: 4px;
-    min-height: 25px;
-  }
-</style>
-
-<%layout:skeleton>
-  <%def name="title()">
-    <h4>${ _('Snippet editor for') } <strong>${ hue_collection.name }</strong></h4>
-  </%def>
-
-  <%def name="navigation()">
-    ${ layout.sidebar(hue_collection, 'template') }
-  </%def>
-
-  <%def name="content()">
-    <ul class="nav nav-tabs" style="margin-bottom:0; margin-top:10px">
-      <li class="active"><a href="#visual" data-toggle="tab">${_('Visual Editor')}</a></li>
-      <li><a href="#preview" data-toggle="tab">${_('Preview')}</a></li>
-      <li><a href="#source" data-toggle="tab">${_('Source')}</a></li>
-      <li><a href="#extra" data-toggle="tab">${_('Advanced')}</a></li>
-    </ul>
-    <div class="well">
-    <div class="tab-content">
-      <div class="tab-pane active" id="visual">
-        <div class="row-fluid">
-          <div class="span9">
-            <div id="toolbar"></div>
-            <div id="content-editor" class="clear">${ hue_collection.result.get_template() | n,unicode }</div>
-            <div id="cloud-template" class="btn-group">
-              <a title="${_('Cloud Template')}" class="btn toolbar-btn toolbar-cmd">
-                <i class="fa fa-cloud-download" style="margin-top:2px;"></i>
-              </a>
-            </div>
-            <div id="load-template" class="btn-group">
-              <a title="${_('Layout')}" class="btn toolbar-btn toolbar-cmd">
-                <i class="fa fa-th-large" style="margin-top:2px;"></i>
-              </a>
-            </div>
-          </div>
-          <div class="span3">
-            <div class="card card-home">
-              <h2 class="card-heading simple">${_('Available Fields')}</h2>
-              <div class="card-body">
-                <p>
-                  <select data-bind="options: availableFields, value: selectedVisualField" class="input-large chosen-select"></select>
-                  <button title="${ _('Click on this button to add the field') }" class="btn plus-btn" data-bind="click: $root.addFieldToVisual">
-                    <i class="fa fa-plus"></i>
-                  </button>
-                  <div class="clearfix"></div>
-                </p>
-              </div>
-            </div>
-            <div class="card card-home">
-              <h2 class="card-heading simple">${_('Available Functions')}</h2>
-              <div class="card-body">
-                <select id="visualFunctions" data-bind="value: selectedVisualFunction" class="input-large chosen-select">
-                  <option title="${ _('Formats date or timestamp in DD-MM-YYYY') }" value="{{#date}} {{/date}}">{{#date}}</option>
-                  <option title="${ _('Formats date or timestamp in HH:mm:ss') }" value="{{#time}} {{/time}}">{{#time}}</option>
-                  <option title="${ _('Formats date or timestamp in DD-MM-YYYY HH:mm:ss') }" value="{{#datetime}} {{/datetime}}">{{#datetime}}</option>
-                  <option title="${ _('Formats a date in the full format') }" value="{{#fulldate}} {{/fulldate}}">{{#fulldate}}</option>
-                  <option title="${ _('Formats a date as a Unix timestamp') }" value="{{#timestamp}} {{/timestamp}}">{{#timestamp}}</option>
-                  <option title="${ _('Formats a Unix timestamp as Ns, Nmin, Ndays... ago') }" value="{{#fromnow}} {{/fromnow}}">{{#fromnow}}</option>
-                  <option title="${ _('Downloads and embed the file in the browser') }" value="{{#embeddeddownload}} {{/embeddeddownload}}">{{#embeddeddownload}}</option>
-                  <option title="${ _('Downloads the linked file') }" value="{{#download}} {{/download}}">{{#download}}</option>
-                  <option title="${ _('Preview file in File Browser') }" value="{{#preview}} {{/preview}}">{{#preview}}</option>
-                  <option title="${ _('Truncate a value after 100 characters') }" value="{{#truncate100}} {{/truncate100}}">{{#truncate100}}</option>
-                  <option title="${ _('Truncate a value after 250 characters') }" value="{{#truncate250}} {{/truncate250}}">{{#truncate250}}</option>
-                  <option title="${ _('Truncate a value after 500 characters') }" value="{{#truncate500}} {{/truncate500}}">{{#truncate500}}</option>
-                </select>
-                <button title="${ _('Click on this button to add the field') }" class="btn plus-btn" data-bind="click: $root.addFunctionToVisual">
-                  <i class="fa fa-plus"></i>
-                </button>
-                <div class="clearfix"></div>
-                <p class="muted" style="margin-top: 10px"></p>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <div class="tab-pane" id="source">
-        <div class="row-fluid">
-          <div class="span9" style="padding-top: 10px">
-            <textarea id="template-source"></textarea>
-          </div>
-          <div class="span3">
-            <div class="card card-home">
-              <h2 class="card-heading simple">${_('Available Fields')}</h2>
-              <div class="card-body">
-                <p>
-                  <select data-bind="options: availableFields, value: selectedSourceField" class="input-medium chosen-select"></select>
-                  <button title="${ _('Click on this button to add the field') }" class="btn plus-btn" data-bind="click: $root.addFieldToSource">
-                    <i class="fa fa-plus"></i>
-                  </button>
-                  <div class="clearfix"></div>
-                </p>
-              </div>
-            </div>
-            <div class="card card-home">
-              <h2 class="card-heading simple">${_('Available Functions')}</h2>
-              <div class="card-body">
-                <select id="sourceFunctions" data-bind="value: selectedSourceFunction" class="input-medium chosen-select">
-                  <option title="${ _('Formats a date in the DD-MM-YYYY format') }" value="{{#date}} {{/date}}">{{#date}}</option>
-                  <option title="${ _('Formats a date in the HH:mm:ss format') }" value="{{#time}} {{/time}}">{{#time}}</option>
-                  <option title="${ _('Formats a date in the DD-MM-YYYY HH:mm:ss format') }" value="{{#datetime}} {{/datetime}}">{{#datetime}}</option>
-                  <option title="${ _('Formats a date in the full format') }" value="{{#fulldate}} {{/fulldate}}">{{#fulldate}}</option>
-                  <option title="${ _('Formats a date as a Unix timestamp') }" value="{{#timestamp}} {{/timestamp}}">{{#timestamp}}</option>
-                  <option title="${ _('Shows the relative time') }" value="{{#fromnow}} {{/fromnow}}">{{#fromnow}}</option>
-                  <option title="${ _('Downloads and embed the file in the browser') }" value="{{#embeddeddownload}} {{/embeddeddownload}}">{{#embeddeddownload}}</option>
-                  <option title="${ _('Downloads the linked file') }" value="{{#download}} {{/download}}">{{#download}}</option>
-                  <option title="${ _('Preview file in File Browser') }" value="{{#preview}} {{/preview}}">{{#preview}}</option>
-                  <option title="${ _('Truncate a value after 100 characters') }" value="{{#truncate100}} {{/truncate100}}">{{#truncate100}}</option>
-                  <option title="${ _('Truncate a value after 250 characters') }" value="{{#truncate250}} {{/truncate250}}">{{#truncate250}}</option>
-                  <option title="${ _('Truncate a value after 500 characters') }" value="{{#truncate500}} {{/truncate500}}">{{#truncate500}}</option>
-                </select>
-                <button title="${ _('Click on this button to add the field') }" class="btn plus-btn" data-bind="click: $root.addFunctionToSource">
-                  <i class="fa fa-plus"></i>
-                </button>
-                <div class="clearfix"></div>
-                <p class="muted" style="margin-top: 10px"></p>
-              </div>
-            </div>
-          </div>
-        </div>
-
-      </div>
-
-      <div class="tab-pane" id="preview">
-        <div id="preview-container"></div>
-      </div>
-
-      <div class="tab-pane" id="extra">
-        <div class="row-fluid">
-          <div class="span12">
-            <span class="muted"> ${ _('Here you can define custom CSS classes or Javascript functions that you can use in your template.') }</span><br/><br/>
-            <textarea id="template-extra">${ hue_collection.result.get_extracode() | n,unicode }</textarea>
-          </div>
-        </div>
-
-      </div>
-    </div>
-
-    <div class="form-actions">
-      <a class="btn btn-primary" id="save-template">${_('Save')}</a>
-    </div>
-
-    <div id="load-template-modal" class="modal hide fade">
-      <div class="modal-header">
-        <button type="button" class="close" data-dismiss="modal">&times;</button>
-        <h3>${_('Insert layout')}</h3>
-      </div>
-      <div class="modal-body">
-        <div id="layoutCarousel" class="carousel slide">
-          <div class="carousel-inner">
-            <div class="item active">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span12">12</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span1">1</div>
-                  <div class="span11">11</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span2">2</div>
-                  <div class="span10">10</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span3">3</div>
-                  <div class="span9">9</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span4">4</div>
-                  <div class="span8">8</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span6">6</div>
-                  <div class="span6">6</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span4">4</div>
-                  <div class="span4">4</div>
-                  <div class="span4">4</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span3">3</div>
-                  <div class="span3">3</div>
-                  <div class="span3">3</div>
-                  <div class="span3">3</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span8">8</div>
-                  <div class="span4">4</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span9">9</div>
-                  <div class="span3">3</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span10">10</div>
-                  <div class="span2">2</div>
-                </div>
-              </div>
-            </div>
-            <div class="item">
-              <div class="tmpl">
-                <div class="row-fluid">
-                  <div class="span11">11</div>
-                  <div class="span1">1</div>
-                </div>
-              </div>
-            </div>
-          </div>
-          <a class="left carousel-control" href="#layoutCarousel" data-slide="prev">&laquo;</a>
-          <a class="right carousel-control" href="#layoutCarousel" data-slide="next">&raquo;</a>
-        </div>
-      </div>
-      <div class="modal-footer">
-        <a href="#" class="btn" data-dismiss="modal">${_('Cancel')}</a>
-        <button type="button" id="load-template-btn" href="#" class="btn btn-primary" disabled="disabled">${_('Insert layout')}</button>
-      </div>
-    </div>
-
-    <div id="cloud-template-modal" class="modal hide fade">
-      <div class="modal-header">
-        <button type="button" class="close" data-dismiss="modal">&times;</button>
-        <h3>${_('Load a template')}</h3>
-      </div>
-      <div class="modal-body">
-        <div id="cloud-loader" style="text-align: center">
-          <img src="/static/art/spinner.gif" />
-        </div>
-      </div>
-      <div class="modal-footer">
-        <a href="#" class="btn" data-dismiss="modal">${_('Cancel')}</a>
-        <button type="button" id="cloud-template-btn" href="#" class="btn btn-primary" disabled="disabled">${_('Load template')}</button>
-      </div>
-    </div>
-    </div>
-  </%def>
-</%layout:skeleton>
-
-<span id="extraCode">
-  ${ hue_collection.result.get_extracode() | n,unicode }
-</span>
-
-<link rel="stylesheet" href="/static/css/freshereditor.css">
-<link rel="stylesheet" href="/static/ext/css/codemirror.css">
-
-<script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/shortcut.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/js/freshereditor.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/codemirror-3.11.js"></script>
-<script src="/static/ext/js/moment.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/codemirror-xml.js"></script>
-<script src="/static/ext/js/mustache.js"></script>
-<script src="/search/static/js/search.utils.js"></script>
-
-<script type="text/javascript">
-
-  $(document).ready(function () {
-    $("#layoutCarousel").carousel("pause");
-
-    $("#content-editor").on("mouseup", function () {
-      storeSelection();
-    });
-
-    $("#content-editor").on("keyup", function () {
-      storeSelection();
-    });
-
-    function storeSelection() {
-      if (window.getSelection) {
-        // IE9 and non-IE
-        sel = window.getSelection();
-        if (sel.getRangeAt && sel.rangeCount) {
-          range = sel.getRangeAt(0);
-          $('#content-editor').data("range", range);
-        }
-      }
-      else if (document.selection && document.selection.type != "Control") {
-        // IE < 9
-        $('#content-editor').data("selection", document.selection);
-      }
-    }
-
-    function pasteHtmlAtCaret(html) {
-      var sel, range;
-      if (window.getSelection) {
-        // IE9 and non-IE
-        sel = window.getSelection();
-        if (sel.getRangeAt && sel.rangeCount) {
-          if ($('#content-editor').data("range")) {
-            range = $('#content-editor').data("range");
-          }
-          else {
-            range = sel.getRangeAt(0);
-          }
-          range.deleteContents();
-
-          // Range.createContextualFragment() would be useful here but is
-          // non-standard and not supported in all browsers (IE9, for one)
-          var el = document.createElement("div");
-          el.innerHTML = html;
-          var frag = document.createDocumentFragment(), node, lastNode;
-          while ((node = el.firstChild)) {
-            lastNode = frag.appendChild(node);
-          }
-          range.insertNode(frag);
-
-          // Preserve the selection
-          if (lastNode) {
-            range = range.cloneRange();
-            range.setStartAfter(lastNode);
-            range.collapse(true);
-            sel.removeAllRanges();
-            sel.addRange(range);
-          }
-        }
-      } else if (document.selection && document.selection.type != "Control") {
-        // IE < 9
-        if ($('#content-editor').data("selection")) {
-          $('#content-editor').data("selection").createRange().pasteHTML(html);
-        }
-        else {
-          document.selection.createRange().pasteHTML(html);
-        }
-      }
-    }
-
-    function ViewModel() {
-      var self = this;
-      self.availableFields = ko.observableArray(${ hue_collection.fields(user) | n,unicode });
-      self.selectedVisualField = ko.observable();
-      self.selectedVisualFunction = ko.observable();
-      self.selectedVisualFunction.subscribe(function (newValue) {
-        var _vf = $("#visualFunctions");
-        _vf.siblings(".muted").text(_vf.find(":selected").attr("title"));
-      });
-      self.selectedSourceField = ko.observable();
-      self.selectedSourceFunction = ko.observable();
-      self.selectedSourceFunction.subscribe(function (newValue) {
-        var _sf = $("#sourceFunctions");
-        _sf.siblings(".muted").text(_sf.find(":selected").attr("title"));
-      });
-      self.lastIndex = ko.observable(0);
-      self.addFieldToVisual = function () {
-        $("#content-editor").focus();
-        pasteHtmlAtCaret("{{" + self.selectedVisualField() + "}}");
-      };
-      self.addFieldToSource = function () {
-        templateSourceMirror.replaceSelection("{{" + self.selectedSourceField() + "}}");
-      };
-      self.addFunctionToVisual = function () {
-        $("#content-editor").focus();
-        pasteHtmlAtCaret(self.selectedVisualFunction());
-      };
-      self.addFunctionToSource = function () {
-        templateSourceMirror.replaceSelection(self.selectedSourceFunction());
-      };
-    };
-
-    var viewModel = new ViewModel();
-    ko.applyBindings(viewModel);
-    $(".chosen-select").chosen({width: "75%"});
-
-    var samples = ${ sample_data | n,unicode };
-    var templateSourceEl = $("#template-source")[0];
-    var templateSourceMirror = CodeMirror(function (elt) {
-      templateSourceEl.parentNode.replaceChild(elt, templateSourceEl);
-    }, {
-      value: templateSourceEl.value,
-      readOnly: false,
-      lineNumbers: true
-    });
-
-    var templateExtraEl = $("#template-extra")[0];
-    var templateExtraMirror = CodeMirror(function (elt) {
-      templateExtraEl.parentNode.replaceChild(elt, templateExtraEl);
-    }, {
-      value: templateExtraEl.value,
-      readOnly: false,
-      lineNumbers: true
-    });
-
-    $("#content-editor").freshereditor({
-      toolbar_selector: "#toolbar",
-      excludes: ['strikethrough', 'removeFormat', 'insertorderedlist', 'justifyfull', 'insertheading1', 'insertheading2', 'superscript', 'subscript']
-    });
-    $("#content-editor").freshereditor("edit", true);
-
-    // Force refresh on tab change
-    $("a[data-toggle='tab']").on("shown", function (e) {
-      if ($(e.target).attr("href") == "#source") {
-        templateSourceMirror.setValue(stripHtmlFromFunctions($("#content-editor").html()));
-        templateSourceMirror.setSize("100%", 450);
-        window.setTimeout(function(){
-          for (var i = 0; i < templateSourceMirror.lineCount(); i++) {
-            templateSourceMirror.indentLine(i);
-          }
-        }, 100);
-
-        templateSourceMirror.refresh();
-      }
-      if ($(e.target).attr("href") == "#extra") {
-        templateExtraMirror.setSize("100%", 420);
-        templateExtraMirror.refresh();
-      }
-      if ($(e.target).attr("href") == "#preview") {
-        $("#preview-container").empty();
-        var _mustacheTmpl = fixTemplateDotsAndFunctionNames($("#content-editor").html());
-        $(samples).each(function (cnt, item) {
-          addTemplateFunctions(item);
-          $("<div>").addClass("preview-row").html(Mustache.render(_mustacheTmpl, item)).appendTo($("#preview-container"));
-        });
-      }
-    });
-
-    var sourceDelay = -1;
-    templateSourceMirror.on("change", function () {
-      clearTimeout(sourceDelay);
-      sourceDelay = setTimeout(function () {
-        $("#content-editor").html(stripHtmlFromFunctions(templateSourceMirror.getValue()));
-      }, 300);
-    });
-
-    var extraDelay = -1;
-    templateExtraMirror.on("change", function () {
-      clearTimeout(extraDelay);
-      extraDelay = setTimeout(function () {
-        $("#extraCode").html($.parseHTML(templateExtraMirror.getValue()));
-      }, 300);
-    });
-
-    $("#load-template").prependTo($("#toolbar .btn-toolbar")).removeClass("hide");
-    $("#cloud-template").prependTo($("#toolbar .btn-toolbar")).removeClass("hide");
-
-    $("#load-template-modal").modal({
-      show: false
-    });
-
-    $("#cloud-template-modal").modal({
-      show: false
-    });
-
-    $("#load-template .btn").on("hover", function () {
-      $("#load-template").popover("hide");
-    });
-
-    $("#load-template .btn").click(function () {
-      $("#load-template-btn").button("reset");
-      $("#load-template").popover("hide");
-      $("#load-template-modal").modal("show");
-    });
-
-    $("#cloud-template .btn").click(function () {
-      $("#cloud-loader").show();
-      $(".cloud-tmpl").remove();
-      $("#load-template").popover("hide");
-      $("#cloud-template-modal").modal("show");
-      $.get("/search/static/templates/templates.xml", function (xml) {
-        var $xml = $(xml);
-        $.each($xml.find("template"), function () {
-          var _this = $(this);
-          var _tmpl = $("<div>");
-          _tmpl.addClass("cloud-tmpl").html("<h4>" + _this.find("title").text() + "</h4><img src='" + _this.find("img").text() + "'/>");
-          _tmpl.data("source", _this.find("source").text());
-          _tmpl.data("additional", _this.find("additional").text());
-          _tmpl.appendTo("#cloud-template-modal .modal-body");
-          _tmpl.on("click", function () {
-            $(".cloud-tmpl").removeClass("selected");
-            $(this).addClass("selected");
-            $("#cloud-template-btn").button("reset");
-          });
-        });
-        $("#cloud-loader").hide();
-      });
-    });
-
-    $("#cloud-template-btn").on("click", function () {
-      templateSourceMirror.setValue($(".cloud-tmpl.selected").data("source"));
-      $("#content-editor").html(stripHtmlFromFunctions(templateSourceMirror.getValue()));
-      templateExtraMirror.setValue($(".cloud-tmpl.selected").data("additional"));
-      $("#cloud-template-modal").modal("hide");
-    });
-
-    if ($("#content-editor").text().trim() == "") {
-      $("#load-template").popover({
-        placement: "bottom",
-        title: "${ _('Start with this!') }",
-        content: "${ _('You can add a layout from here') }"
-      });
-      $("#load-template").popover("show");
-    }
-
-    $("#load-template-btn").click(function () {
-      $("#load-template-modal").modal("hide");
-      $("#content-editor").focus();
-      var _clone = $("#layoutCarousel .item.active .tmpl").clone();
-      _clone.find("[class*='span']").text("");
-      pasteHtmlAtCaret(_clone.html());
-    });
-
-    $("body").click(function () {
-      $("#load-template").popover("hide");
-    });
-
-    $("#save-template").click(function () {
-      $.ajax("${ url('search:admin_collection_template', collection_id=hue_collection.id) }", {
-        data: {
-          'template': ko.utils.stringifyJson($("#content-editor").html()),
-          'extracode': ko.utils.stringifyJson(templateExtraMirror.getValue())
-        },
-        contentType: 'application/json',
-        type: 'POST',
-        success: function () {
-          $(document).trigger("info", "${_('Template updated')}");
-        },
-        error: function (data) {
-          $(document).trigger("error", "${_('Error: ')}" + data);
-        },
-        complete: function () {
-          $("#save-template").button('reset');
-        }
-      });
-    });
-  });
-</script>
-
-${ commonfooter(messages) | n,unicode }

+ 0 - 232
apps/search/src/search/templates/admin_collections_create_file.mako

@@ -1,232 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-  from desktop.views import commonheader, commonfooter
-  from django.utils.translation import ugettext as _
-%>
-
-<%namespace name="macros" file="macros.mako" />
-<%namespace name="actionbar" file="actionbar.mako" />
-
-${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
-
-<link rel="stylesheet" href="/search/static/css/admin.css">
-<link rel="stylesheet" href="/static/ext/chosen/chosen.min.css">
-
-<div class="search-bar" style="height: 30px">
-  <div class="pull-right" style="margin-top: 4px; margin-right: 20px">
-    <a href="${ url('search:index') }"><i class="fa fa-share"></i> ${ _('Search page') }</a>
-  </div>
-  <h4>${_('Collection Manager')}</h4>
-</div>
-
-
-<div class="container-fluid">
-  <div class="row-fluid">
-
-    <div class="span3">
-      <div class="sidebar-nav card-small">
-        <ul class="nav nav-list">
-          <li class="nav-header">${_('Actions')}</li>
-          <li><a href="/search/admin/collections_create_file"><i class="fa fa-files-o"></i> ${_('Create a new collection from a file')}</a></li>
-          <li><a href="/search/admin/collections_create_manual"><i class="fa fa-wrench"></i> ${_('Create a new collection manually')}</a></li>
-        </ul>
-      </div>
-    </div>
-
-    <div class="span9">
-      <div class="card wizard">
-        <h1 class="card-heading simple">${_("Create collection file")}</h1>
-        <div class="card-body">
-          <form class="form form-horizontal">
-            <div data-bind="template: { 'name': wizard.current().name, 'afterRender': createUploader }"></div>
-            <br />
-            <a data-bind="routie: 'wizard/' + wizard.previous().url(), visible: wizard.hasPrevious" class="btn btn-info" href="javascript:void(0)">${_('Previous')}</a>
-            <a data-bind="routie: 'wizard/' + wizard.next().url(), visible: wizard.hasNext" class="btn btn-info" href="javascript:void(0)">${_('Next')}</a>
-            <a data-bind="click: save, visible: !wizard.hasNext()" class="btn btn-info" href="javascript:void(0)">${_('Finish')}</a>
-          </form>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</div>
-
-
-<!-- Start Wizard -->
-<script type="text/html" id="step-1">
-  <div class="control-group" data-bind="css: {'error': collection.name.errors().length > 0}">
-    <label for="name" class="control-label">${_("Name")}</label>
-    <div class="controls">
-      <input data-bind="value: collection.name" name="name" type="text" placeholder="${_('Name of collection')}" />
-    </div>
-  </div>
-
-  <div class="control-group">
-    <label for="name" class="control-label">${_("Files")}</label>
-    <div class="controls">
-      <div id="upload-index"></div>
-    </div>
-  </div>
-</script>
-
-<script type="text/html" id="step-2">
-  <div class="control-group" data-bind="css: {'error': collection.name.errors().length > 0}">
-    <label for="name" class="control-label">${_("Name")}</label>
-    <div class="controls">
-      <select data-bind="options: $root.fieldSeparators, value: fieldSeparator" name="type"></select>
-    </div>
-  </div>
-</script>
-
-<script type="text/html" id="step-3">
-  <formset data-bind="foreach: collection.fields">
-    <div class="control-group" data-bind="css: {'error': name.errors().length > 0}">
-      <label for="name" class="control-label">${_("Name")}</label>
-      <div class="controls">
-        <input data-bind="value: name" name="name" type="text" placeholder="${_('Name of field')}" />
-      </div>
-    </div>
-
-    <div class="control-group">
-      <label for="type" class="control-label">${_("Type")}</label>
-      <div class="controls">
-        <select data-bind="options: $root.fieldTypes, value: type" name="type"></select>
-      </div>
-    </div>
-
-    <a data-bind="click: remove" href="javascript:void(0)" class="btn btn-error"><i class="fa fa-minus"></i>&nbsp;${_("Remove field")}</a>
-  </formset>
-
-  <br />
-  <br />
-  <a data-bind="click: collection.newField" href="javascript:void(0)" class="btn btn-info"><i class="fa fa-plus"></i>&nbsp;${_("Add field")}</a>
-</script>
-<!-- End Wizard -->
-
-
-<script src="/static/ext/js/routie-0.3.0.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/knockout.mapping-2.3.2.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/create-collections.ko.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/chosen/chosen.jquery.min.js" type="text/javascript" charset="utf-8"></script>
-
-<script type="text/javascript">
-function validateFileAndName() {
-  var ret = true;
-  if (!vm.collection.name()) {
-    vm.collection.name.errors.push("${ _('Name is missing') }");
-    ret = false;
-  } else {
-    vm.collection.name.errors.removeAll();
-  }
-
-  ret &= validateFields();
-  return ret;
-}
-
-function validateFields() {
-  var ret = true;
-  $.each(vm.collection.fields(), function(index, field) {
-    if (!field.name()) {
-      field.name.errors.push("${ _('Field name is missing') }");
-      ret = false;
-    } else {
-      field.name.errors.removeAll();
-    }
-
-    if (!field.type()) {
-      field.type.errors.push("${ _('Field type is missing') }");
-      ret = false;
-    } else {
-      field.type.errors.removeAll();
-    }
-  });
-  return ret;
-}
-
-function validateSeparator() {
-  if (uploader) {
-    uploader.finishUpload();
-    return true;
-  } else {
-    return false;
-  }
-}
-
-var vm = new CreateCollectionViewModel([
-  {'name': 'step-1', 'url': 'name', 'validate': validateFileAndName},
-  {'name': 'step-2', 'url': 'separator', 'validate': validateSeparator},
-  {'name': 'step-3', 'url': 'fields', 'validate': validateFields}
-]);
-
-routie({
-  "wizard/:step": function(step) {
-    vm.wizard.setIndexByUrl(step);
-  },
-  "*": function() {
-    routie('wizard/name');
-  },
-});
-
-var uploader;
-
-function createUploader() {
-  if ($("#upload-index").length > 0) {
-    var num_of_pending_uploads = 0;
-    uploader = new qq.CollectionFileUploader({
-      element: $("#upload-index")[0],
-      action: "/search/fields/parse",
-      template:'<div class="qq-uploader">' +
-              '<div class="qq-upload-drop-area"><span>${_('Drop files here to upload')}</span></div>' +
-              '<div class="qq-upload-button">${_('Select files')}</div>' +
-              '<ul class="qq-upload-list"></ul>' +
-              '</div>',
-      fileTemplate:'<li>' +
-              '<span class="qq-upload-file"></span>' +
-              '<span class="qq-upload-spinner"></span>' +
-              '<span class="qq-upload-size"></span>' +
-              '<a class="qq-upload-cancel" href="#">${_('Cancel')}</a>' +
-              '<span class="qq-upload-failed-text">${_('Failed')}</span>' +
-              '</li>',
-      params:{
-        fileFieldLabel: 'collections_file'
-      },
-      onComplete: function(id, fileName, response) {
-        num_of_pending_uploads--;
-        if (response.status != 0) {
-          $(document).trigger("error", "${ _('Error: ') }" + response['data']);
-        } else if (num_of_pending_uploads == 0) {
-          // Infer fields
-          vm.inferFields(response['data']);
-        }
-      },
-      onSubmit: function(id, fileName, responseJSON) {
-        uploader._options.params['fieldSeparator'] = vm.fieldSeparator();
-        num_of_pending_uploads++;
-      },
-      multiple: false,
-      debug: false,
-    });
-  }
-}
-
-ko.applyBindings(vm);
-
-</script>
-
-${ commonfooter(messages) | n,unicode }

+ 0 - 162
apps/search/src/search/templates/admin_collections_create_manual.mako

@@ -1,162 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-  from desktop.views import commonheader, commonfooter
-  from django.utils.translation import ugettext as _
-%>
-
-<%namespace name="macros" file="macros.mako" />
-<%namespace name="actionbar" file="actionbar.mako" />
-
-${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
-
-<link rel="stylesheet" href="/search/static/css/admin.css">
-<link rel="stylesheet" href="/static/ext/chosen/chosen.min.css">
-
-<div class="search-bar" style="height: 30px">
-  <div class="pull-right" style="margin-top: 4px; margin-right: 20px">
-    <a href="${ url('search:index') }"><i class="fa fa-share"></i> ${ _('Search page') }</a>
-  </div>
-  <h4>${_('Collection Manager')}</h4>
-</div>
-
-
-<div class="container-fluid">
-  <div class="row-fluid">
-
-    <div class="span3">
-      <div class="sidebar-nav card-small">
-        <ul class="nav nav-list">
-          <li class="nav-header">${_('Actions')}</li>
-          <li><a href="/search/admin/collections_create_file"><i class="fa fa-files-o"></i> ${_('Create a new collection from a file')}</a></li>
-          <li><a href="/search/admin/collections_create_manual"><i class="fa fa-wrench"></i> ${_('Create a new collection manually')}</a></li>
-        </ul>
-      </div>
-    </div>
-
-    <div class="span9">
-      <div class="card wizard">
-        <h1 class="card-heading simple">${_("Create collection manually")}</h1>
-        <div class="card-body">
-          <form class="form form-horizontal">
-            <div data-bind="template: { 'name': wizard.current().name }"></div>
-            <br />
-            <a data-bind="routie: 'wizard/' + wizard.previous().url(), visible: wizard.hasPrevious" class="btn btn-info" href="javascript:void(0)">${_('Previous')}</a>
-            <a data-bind="routie: 'wizard/' + wizard.next().url(), visible: wizard.hasNext" class="btn btn-info" href="javascript:void(0)">${_('Next')}</a>
-            <a data-bind="click: save, visible: !wizard.hasNext()" class="btn btn-info" href="javascript:void(0)">${_('Finish')}</a>
-          </form>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</div>
-
-
-<!-- Start Wizard -->
-<script type="text/html" id="step-1">
-  <div class="control-group" data-bind="css: {'error': collection.name.errors().length > 0}">
-    <label for="name" class="control-label">${_("Name")}</label>
-    <div class="controls">
-      <input data-bind="value: collection.name" name="name" type="text" placeholder="${_('Name of collection')}" />
-    </div>
-  </div>
-</script>
-
-<script type="text/html" id="step-2">
-  <formset data-bind="foreach: collection.fields">
-    <div class="control-group" data-bind="css: {'error': name.errors().length > 0}">
-      <label for="name" class="control-label">${_("Name")}</label>
-      <div class="controls">
-        <input data-bind="value: name" name="name" type="text" placeholder="${_('Name of field')}" />
-      </div>
-    </div>
-
-    <div class="control-group">
-      <label for="type" class="control-label">${_("Type")}</label>
-      <div class="controls">
-        <select data-bind="options: $root.fieldTypes, value: type" name="type"></select>
-      </div>
-    </div>
-
-    <a data-bind="click: remove" href="javascript:void(0)" class="btn btn-error"><i class="fa fa-minus"></i>&nbsp;${_("Remove field")}</a>
-  </formset>
-
-  <br />
-  <br />
-  <a data-bind="click: collection.newField" href="javascript:void(0)" class="btn btn-info"><i class="fa fa-plus"></i>&nbsp;${_("Add field")}</a>
-</script>
-<!-- End Wizard -->
-
-
-<script src="/static/ext/js/routie-0.3.0.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/knockout.mapping-2.3.2.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/create-collections.ko.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/chosen/chosen.jquery.min.js" type="text/javascript" charset="utf-8"></script>
-
-<script type="text/javascript">
-function validateName() {
-  var ret = true;
-  if (!vm.collection.name()) {
-    vm.collection.name.errors.push("${ _('Name is missing') }");
-    ret = false;
-  } else {
-    vm.collection.name.errors.removeAll();
-  }
-  return ret;
-}
-
-function validateFields() {
-  var ret = true;
-  $.each(vm.collection.fields(), function(index, field) {
-    if (!field.name()) {
-      field.name.errors.push("${ _('Field name is missing') }");
-      ret = false;
-    } else {
-      field.name.errors.removeAll();
-    }
-
-    if (!field.type()) {
-      field.type.errors.push("${ _('Field type is missing') }");
-      ret = false;
-    } else {
-      field.type.errors.removeAll();
-    }
-  });
-  return ret;
-}
-
-var vm = new CreateCollectionViewModel([
-  {'name': 'step-1', 'url': 'name', 'validate': validateName},
-  {'name': 'step-2', 'url': 'fields', 'validate': validateFields}
-]);
-
-routie({
-  "wizard/:step": function(step) {
-    vm.wizard.setIndexByUrl(step);
-  },
-  "*": function() {
-    routie('wizard/name');
-  },
-});
-
-ko.applyBindings(vm);
-
-</script>
-
-${ commonfooter(messages) | n,unicode }

+ 0 - 511
apps/search/src/search/templates/dashboard.mako

@@ -1,511 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-from desktop.views import commonheader, commonfooter
-from django.utils.translation import ugettext as _
-from django.utils.dateparse import parse_datetime
-from search.api import utf_quoter
-import urllib
-import math
-import time
-%>
-
-${ commonheader(_('Search'), "search", user, "70px") | n,unicode }
-
-<style type="text/css">
-  .dashboard .container-fluid {
-    padding: 10px;
-  }
-
-  .row-container {
-    width: 100%;
-    min-height: 70px;
-  }
-
-  .ui-sortable {
-    background-color: #F6F6F6;
-  }
-
-  .ui-sortable h2 {
-    padding-left: 10px!important;
-  }
-
-  .ui-sortable h2 ul {
-    float: left;
-    margin-right: 10px;
-    font-size: 14px;
-  }
-
-  .ui-sortable:not(.ui-sortable-disabled) h2 {
-    cursor: move;
-  }
-
-  .ui-sortable-disabled {
-    background-color: #FFF;
-  }
-
-  .card-column {
-    border: none;
-    min-height: 400px!important;
-  }
-
-  .card-widget {
-    padding-top: 0;
-  }
-
-  .card-toolbar {
-    margin: 0;
-    padding: 4px;
-    padding-top: 10px;
-  }
-
-  .row-header {
-    background-color: #F6F6F6;
-    display: inline;
-    padding: 4px;
-  }
-
-  #emptyDashboard {
-    position: absolute;
-    right: 14px;
-    top: 80px;
-    color: #666;
-    font-size: 20px;
-  }
-
-  .emptyRow {
-    margin-top: 10px;
-    margin-left: 140px;
-    color: #666;
-    font-size: 18px;
-  }
-
-  .preview-row {
-    background-color: #DDD;
-    min-height: 400px!important;
-    margin-top: 30px;
-  }
-
-  .draggable-widget {
-    width: 100px;
-    text-align: center;
-    float: left;
-    border: 1px solid #CCC;
-    margin-top: 10px;
-    margin-right: 10px;
-    cursor: move;
-  }
-  .draggable-widget a {
-    font-size: 58px;
-    line-height: 76px;
-    cursor: move;
-  }
-
-  .unselectable {
-    -webkit-touch-callout: none;
-    -webkit-user-select: none;
-    -khtml-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
-  }
-
-</style>
-
-<div class="navbar navbar-inverse navbar-fixed-top nokids">
-  <div class="navbar-inner">
-    <div class="container-fluid">
-      <div class="pull-right">
-        <button type="button" data-bind="click: toggleEditing, css: {'btn': true, 'btn-inverse': isEditing}"><i class="fa fa-pencil"></i></button>
-      </div>
-      <div class="nav-collapse">
-        <ul class="nav">
-          <li class="currentApp">
-            <a href="/search">
-              <img src="/search/static/art/icon_search_24.png">
-              Collection name
-            </a>
-           </li>
-        </ul>
-      </div>
-    </div>
-  </div>
-</div>
-
-<div class="card card-toolbar" data-bind="slideVisible: isEditing">
-  <div style="float: left">
-    <div style="font-weight: bold; color: #999; padding-left: 8px">${_('LAYOUT')}</div>
-    <a href="javascript: oneThirdLeftLayout()" onmouseover="viewModel.previewColumns('oneThirdLeft')" onmouseout="viewModel.previewColumns('')"><img src="/search/static/art/layout_onethirdleft.png" /></a>
-    <a href="javascript: oneThirdRightLayout()" onmouseover="viewModel.previewColumns('oneThirdRight')" onmouseout="viewModel.previewColumns('')"><img src="/search/static/art/layout_onethirdright.png" /></a>
-    <a href="javascript: fullLayout()" onmouseover="viewModel.previewColumns('full')" onmouseout="viewModel.previewColumns('')"><img src="/search/static/art/layout_full.png" /></a>
-  </div>
-
-  <div style="float: left; margin-left: 20px" data-bind="visible: columns().length > 0">
-    <div style="font-weight: bold; color: #999; padding-left: 8px">${_('WIDGETS')}</div>
-    <div class="draggable-widget" data-bind="draggable: draggableResultset" title="${_('Results')}" rel="tooltip" data-placement="top"><a href="#"><i class="fa fa-table"></i></a></div>    
-    <div class="draggable-widget" data-bind="draggable: draggableFacet" title="${_('Text Facet')}" rel="tooltip" data-placement="top"><a href="#"><i class="fa fa-sort-amount-desc"></i></a></div>    
-    <div class="draggable-widget" data-bind="draggable: draggableBar" title="${_('Timeline')}" rel="tooltip" data-placement="top"><a href="#"><i class="hcha hcha-bar-chart"></i></a></div>
-    <div class="draggable-widget" data-bind="draggable: draggableArea" title="${_('Area Chart')}" rel="tooltip" data-placement="top"><a href="#"><i class="hcha hcha-area-chart"></i></a></div>
-    <div class="draggable-widget" data-bind="draggable: draggablePie" title="${_('Pie Chart')}" rel="tooltip" data-placement="top"><a href="#"><i class="hcha hcha-pie-chart"></i></a></div>
-    <div class="draggable-widget" data-bind="draggable: draggableLine" title="${_('Line Chart')}" rel="tooltip" data-placement="top"><a href="#"><i class="hcha hcha-line-chart"></i></a></div>
-    <div class="draggable-widget" data-bind="draggable: draggableMap" title="${_('Map')}" rel="tooltip" data-placement="top"><a href="#"><i class="hcha hcha-map-chart"></i></a></div>
-  </div>
-  <div class="clearfix"></div>
-</div>
-
-<div id="emptyDashboard" data-bind="visible: !isEditing() && columns().length == 0">
-  <div style="float:left; padding-top: 90px; margin-right: 20px; text-align: center; width: 260px">${_('Click on the pencil to get started with your dashboard!')}</div>
-  <img src="/search/static/art/hint_arrow.png" />
-</div>
-
-<div data-bind="visible: isEditing() && previewColumns() != '' && columns().length == 0">
-  <div class="container-fluid">
-    <div class="row-fluid" data-bind="visible: previewColumns() == 'oneThirdLeft'">
-      <div class="span3 preview-row"></div>
-      <div class="span9 preview-row"></div>
-    </div>
-    <div class="row-fluid" data-bind="visible: previewColumns() == 'oneThirdRight'">
-      <div class="span9 preview-row"></div>
-      <div class="span3 preview-row"></div>
-    </div>
-    <div class="row-fluid" data-bind="visible: previewColumns() == 'full'">
-      <div class="span12 preview-row">
-      </div>
-    </div>
-  </div>
-</div>
-
-<div data-bind="css: {'dashboard': true, 'unselectable': isEditing()}">
-  <div class="container-fluid">
-    <div class="row-fluid" data-bind="template: { name: 'column-template', foreach: columns}">
-    </div>
-    <div class="clearfix"></div>
-  </div>
-</div>
-
-<script type="text/html" id="column-template">
-  <div data-bind="css: klass">
-    <div data-bind="template: { name: 'row-template', foreach: rows}">
-    </div>
-    <div style="height: 50px; padding-left: 6px" data-bind="visible: $root.isEditing">
-      <a href="javascript:void(0)" class="btn" style="margin: 4px; margin-right: 10px" data-bind="click: addEmptyRow"><i class="fa fa-plus"></i> ${_('Add Row')}</a>
-    </div>
-  </div>
-</script>
-
-<script type="text/html" id="row-template">
-  <div class="emptyRow" data-bind="visible: widgets().length == 0 && $index()==0 && $root.isEditing() && $parent.size() > 4">
-    <img src="/search/static/art/hint_arrow_flipped.png" style="float:left; margin-right: 10px"/>
-    <div style="float:left; text-align: center; width: 260px">${_('Drag any of the widgets inside your empty row')}</div>
-    <div class="clearfix"></div>
-  </div>
-  <div class="container-fluid">
-    <div class="row-header" data-bind="visible: $root.isEditing">
-      <span class="muted"><i class="fa fa-ellipsis-h"></i> ${_('Row')}</span>
-      <div style="display: inline; margin-left: 60px">
-        <a href="javascript:void(0)" data-bind="visible:$index()<$parent.rows().length-1, click: function(){moveDown($parent, this)}"><i class="fa fa-chevron-down"></i></a>
-        <a href="javascript:void(0)" data-bind="visible:$index()>0, click: function(){moveUp($parent, this)}"><i class="fa fa-chevron-up"></i></a>
-        <a href="javascript:void(0)" data-bind="visible:$parent.rows().length > 1, click: function(){remove($parent, this)}"><i class="fa fa-times"></i></a>
-      </div>
-    </div>
-    <div class="row-fluid row-container" data-bind="sortable: { template: 'widget-template', data: widgets, isEnabled: $root.isEditing}">
-    </div>
-  </div>
-</script>
-
-<script type="text/html" id="widget-template">
-  <div data-bind="css: klass">
-    <h2 class="card-heading simple">
-      <ul class="inline" data-bind="visible: $root.isEditing">
-        <li><a href="javascript:void(0)" data-bind="click: function(){remove($parent, this)}"><i class="fa fa-times"></i></a></li>
-        <li><a href="javascript:void(0)" data-bind="click: compress, visible: size() > 1"><i class="fa fa-step-backward"></i></a></li>
-        <li><a href="javascript:void(0)" data-bind="click: expand, visible: size() < 12"><i class="fa fa-step-forward"></i></a></li>
-      </ul>
-      <span data-bind="text: name"></span>
-    </h2>
-    <div class="card-body">
-      <p>
-        <div data-bind="template: { name: function() { return widgetType(); }, data: properties }"></div>
-      </p>
-      <div data-bind="visible: $root.isEditing()">
-        This is visible just when we edit.<br/>
-        Common properties:
-        <ul>
-          <li> Name: <input type="text" data-bind="value: name" /></li>
-          <li> Size: <input type="text" data-bind="value: size" /></li>
-          <li> Offset: <input type="text" data-bind="value: offset" /></li>
-        </ul>
-      </div>
-    </div>
-  </div>
-</script>
-
-<script type="text/html" id="empty-widget">
-  This is an empty widget.
-</script>
-
-<script type="text/html" id="facet-widget">
-  This is the facet widget.
-</script>
-
-
-<script type="text/html" id="resultset-widget">
-  This is the resultset widget
-</script>
-
-<script type="text/html" id="timeline-widget">
-  This is the timeline widget
-</script>
-
-<script type="text/html" id="bar-widget">
-  This is the bar widget
-</script>
-
-<script type="text/html" id="pie-widget">
-  This is the pie widget
-</script>
-
-<script type="text/html" id="area-widget">
-  This is the area widget
-</script>
-
-<script type="text/html" id="line-widget">
-  This is the line widget
-</script>
-
-<script type="text/html" id="map-widget">
-  This is the map widget
-</script>
-
-
-<script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/jquery/plugins/jquery-ui-1.10.4.draggable-droppable-sortable.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/knockout-sortable.min.js" type="text/javascript" charset="utf-8"></script>
-
-<link href="/static/ext/css/leaflet.css" rel="stylesheet">
-<link href="/static/ext/css/hue-charts.css" rel="stylesheet">
-
-<script src="/static/ext/js/jquery/plugins/jquery.flot.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/jquery/plugins/jquery.flot.categories.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/leaflet/leaflet.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/js/jquery.blueprint.js"></script>
-
-<script type="text/javascript">
-  ko.bindingHandlers.slideVisible = {
-    init: function (element, valueAccessor) {
-      var value = valueAccessor();
-      $(element).toggle(ko.unwrap(value));
-    },
-    update: function (element, valueAccessor) {
-      var value = valueAccessor();
-      ko.unwrap(value) ? $(element).slideDown(100) : $(element).slideUp(100);
-    }
-  };
-
-  ko.extenders.numeric = function (target, precision) {
-    var result = ko.computed({
-      read: target,
-      write: function (newValue) {
-        var current = target(),
-                roundingMultiplier = Math.pow(10, precision),
-                newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
-                valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
-
-        if (valueToWrite !== current) {
-          target(valueToWrite);
-        } else {
-          if (newValue !== current) {
-            target.notifySubscribers(valueToWrite);
-          }
-        }
-      }
-    }).extend({ notify: 'always' });
-    result(target());
-    return result;
-  };
-
-  var DashBoardViewModel = function () {
-    var self = this;
-    self.previewColumns = ko.observable("");
-    self.columns = ko.observableArray([]);
-    self.isEditing = ko.observable(false);
-    self.draggableFacet = ko.observable(new Widget(12, "Facet", "facet-widget"));
-    self.draggableResultset = ko.observable(new Widget(12, "Results", "resultset-widget"));
-    self.draggableBar = ko.observable(new Widget(12, "Bar Chart", "bar-widget"));
-    self.draggableArea = ko.observable(new Widget(12, "Area Chart", "area-widget"));
-    self.draggableMap = ko.observable(new Widget(12, "Map", "map-widget"));
-    self.draggableLine = ko.observable(new Widget(12, "Line Chart", "line-widget"));
-    self.draggablePie = ko.observable(new Widget(12, "Pie Chart", "pie-widget"));
-    self.toggleEditing = function () {
-      self.isEditing(!self.isEditing());
-    };
-  }
-
-  var Column = function (size, rows) {
-    var self = this;
-    self.size = ko.observable(size);
-    self.rows = ko.observableArray(rows);
-    self.klass = ko.computed(function () {
-      return "card card-home card-column span" + self.size();
-    });
-    self.addEmptyRow = function () {
-      self.addRow();
-    };
-    self.addRow = function (row) {
-      if (typeof row == "undefined" || row == null) {
-        row = new Row([]);
-      }
-      self.rows.push(row);
-    };
-  }
-
-  var Row = function (widgets) {
-    var self = this;
-    self.widgets = ko.observableArray(widgets);
-
-    self.addWidget = function (widget) {
-      self.widgets.push(widget);
-    };
-
-    self.move = function (from, to) {
-      try {
-        viewModel.columns()[to].addRow(self);
-        viewModel.columns()[from].rows.remove(self);
-      }
-      catch (exception) {
-      }
-    }
-
-    self.moveDown = function (col, row) {
-      var _i = col.rows().indexOf(row);
-      if (_i < col.rows().length - 1) {
-        var _arr = col.rows();
-        col.rows.splice(_i, 2, _arr[_i + 1], _arr[_i]);
-      }
-    }
-
-    self.moveUp = function (col, row) {
-      var _i = col.rows().indexOf(row);
-      if (_i >= 1) {
-        var _arr = col.rows();
-        col.rows.splice(_i - 1, 2, _arr[_i], _arr[_i - 1]);
-      }
-    }
-
-    self.remove = function (col, row) {
-      col.rows.remove(row);
-    }
-  }
-
-  var Widget = function (size, name, widgetType, properties, offset) {
-    var self = this;
-    self.size = ko.observable(size).extend({ numeric: 0 });
-
-    self.name = ko.observable(name);
-    self.widgetType = ko.observable(typeof widgetType != "undefined" && widgetType != null ? widgetType : "empty-widget");
-    self.properties = ko.observable(typeof properties != "undefined" && properties != null ? properties : {});
-    self.offset = ko.observable(typeof offset != "undefined" && offset != null ? offset : 0).extend({ numeric: 0 });
-
-
-    self.klass = ko.computed(function () {
-      return "card card-widget span" + self.size() + (self.offset() * 1 > 0 ? " offset" + self.offset() : "");
-    });
-
-    self.expand = function () {
-      self.size(self.size() + 1);
-    }
-    self.compress = function () {
-      self.size(self.size() - 1);
-    }
-
-    self.moveLeft = function () {
-      self.offset(self.offset() - 1);
-    }
-    self.moveRight = function () {
-      self.offset(self.offset() + 1);
-    }
-
-    self.remove = function (row, widget) {
-      row.widgets.remove(widget);
-    }
-  };
-
-  Widget.prototype.clone = function () {
-    return new Widget(this.size(), this.name(), this.widgetType());
-  };
-
-  var viewModel = new DashBoardViewModel()
-  ko.applyBindings(viewModel);
-
-
-  function fullLayout() {
-    setLayout([12]);
-  }
-
-  function oneThirdLeftLayout() {
-    setLayout([3, 9]);
-  }
-
-  function oneThirdRightLayout() {
-    setLayout([9, 3]);
-  }
-
-  function setLayout(colSizes) {
-    // save previous widgets
-    var _allRows = [];
-    $(viewModel.columns()).each(function (cnt, col) {
-      var _tRows = [];
-      $(col.rows()).each(function (icnt, row) {
-        if (row.widgets().length > 0) {
-          _tRows.push(row);
-        }
-      });
-      _allRows = _allRows.concat(_tRows);
-    });
-
-    var _cols = [];
-    var _highestCol = {
-      idx: -1,
-      size: -1
-    };
-    $(colSizes).each(function (cnt, size) {
-      _cols.push(new Column(size, []));
-      if (size > _highestCol.size) {
-        _highestCol.idx = cnt;
-        _highestCol.size = size;
-      }
-    });
-    if (_allRows.length > 0 && _highestCol.idx > -1) {
-      _cols[_highestCol.idx].rows(_allRows);
-    }
-
-    $(_cols).each(function (cnt, col) {
-      if (col.rows().length == 0) {
-        col.rows([new Row([])]);
-      }
-    });
-
-    viewModel.columns(_cols);
-  }
-
-  $(document).ready(function () {
-    fullLayout();
-    viewModel.isEditing(true);
-  });
-</script>
-
-${ commonfooter(messages) | n,unicode }

+ 1741 - 558
apps/search/src/search/templates/search.mako

@@ -17,654 +17,1837 @@
 <%!
 from desktop.views import commonheader, commonfooter
 from django.utils.translation import ugettext as _
-from django.utils.dateparse import parse_datetime
-from search.api import utf_quoter
-import urllib
-import math
-import time
 %>
 
-<%namespace name="macros" file="macros.mako" />
+${ commonheader(_('Search'), "search", user, "80px") | n,unicode }
 
-${ commonheader(_('Search'), "search", user, "90px") | n,unicode }
-
-<link rel="stylesheet" href="/search/static/css/search.css">
-<link href="/static/ext/css/hue-filetypes.css" rel="stylesheet">
-<script src="/static/ext/js/moment.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/search.utils.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/jquery/plugins/jquery.flot.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/jquery/plugins/jquery.flot.selection.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/jquery/plugins/jquery.flot.time.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/js/jquery.blueprint.js" type="text/javascript" charset="utf-8"></script>
-
-<%
-  if "q" not in solr_query:
-    solr_query["q"] = ""
-  else:
-    solr_query["q"] = solr_query["q"].decode("utf8")
-  if "fq" not in solr_query:
-    solr_query["fq"] = ""
-  if "rows" not in solr_query:
-    solr_query["rows"] = ""
-  if "start" not in solr_query:
-    solr_query["start"] = ""
-%>
+<script type="text/javascript">
+  if (window.location.hash != ""){
+    location.href = "/search/?" + window.location.hash.substr(1);
+  }
+</script>
 
 <div class="search-bar">
   % if user.is_superuser:
-    <div class="pull-right" style="margin-top: 6px; margin-right: 40px">
-      <a class="change-settings" href="#"><i class="fa fa-edit"></i> ${ _('Customize this collection') }</a> &nbsp;&nbsp;
-      <a href="${ url('search:admin_collections') }"><i class="fa fa-sitemap"></i> ${ _('Collection manager') }</a>
+    <div class="pull-right" style="padding-right:50px">
+      <button type="button" title="${ _('Edit') }" rel="tooltip" data-placement="bottom" data-bind="click: toggleEditing, css: {'btn': true, 'btn-inverse': isEditing}"><i class="fa fa-pencil"></i></button>
+      <button type="button" title="${ _('Save') }" rel="tooltip" data-placement="bottom" data-loading-text="${ _("Saving...") }" data-bind="click: save, css: {'btn': true}"><i class="fa fa-save"></i></button>
+      <button type="button" title="${ _('Save') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}"><i class="fa fa-cog"></i></button>
+      ## for enable, live search, max number of downloads, change solr
+      <button type="button" title="${ _('Share') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}"><i class="fa fa-link"></i></button>
+      &nbsp;&nbsp;&nbsp;            
+      <a class="btn" href="${ url('search:new_search') }" title="${ _('New') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}"><i class="fa fa-file-o"></i></a>
+      <a class="btn" href="${ url('search:admin_collections') }" title="${ _('Collections') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}"><i class="fa fa-tags"></i></a> 
     </div>
   % endif
-  <form class="form-search" style="margin: 0">
+  
+  <form data-bind="visible: columns().length == 0">  
+    ${ _('Search') }
+    <!-- ko if: $root.initial.collections -->
+    <select data-bind="options: $root.initial.collections, value: $root.collection.name">
+    </select>
+    <!-- /ko -->
+  </form>
+  
+  <form class="form-search" style="margin: 0" data-bind="submit: searchBtn, visible: columns().length != 0"">
     <strong>${_("Search")}</strong>
     <div class="input-append">
       <div class="selectMask">
-        <span class="current-collection"></span>
-        <div id="collectionPopover" class="hide">
-        <ul class="unstyled">
-          % if user.is_superuser:
-            <li><a class="dropdown-collection" href="#" data-value="${ hue_collection.id }" data-settings-url="${ hue_collection.get_absolute_url() }">${ hue_collection.label }</a></li>
-          % else:
-            <li><a class="dropdown-hue_collection" href="#" data-value="${ hue_collection.id }">${ hue_collection.label }</a></li>
-          % endif
-        </ul>
-        </div>
+        <span
+            data-bind="editable: collection.label, editableOptions: {enabled: $root.isEditing(), placement: 'right'}">
+        </span>
+        ##<i class="fa fa-edit" data-bind="visible: $root.isEditing() && ! $root.changeCollection(), click: function(){$root.changeCollection(true);}"></i>
+        <!-- ko if: $root.isEditing() && $root.changeCollection() -->
+        <select data-bind="options: $root.initial.collections, value: $root.collection.name">
+        </select>        
+        <!-- /ko -->
       </div>
 
-      ${ search_form | n,unicode }
-      <button type="submit" id="search-btn" class="btn btn-inverse"><i class="fa fa-search"></i></button>
+      <span data-bind="foreach: query.qs">
+        <input data-bind="value: q" maxlength="256" type="text" class="search-query input-xlarge" style="cursor: auto;">
+        <!-- ko if: $index() >= 1 -->
+        <a class="btn" href="javascript:void(0)" data-bind="click: $root.query.removeQ"><i class="fa fa-minus"></i></a>
+        <!-- /ko -->
+      </span>
 
-      % if response and 'response' in response and 'docs' in response['response'] and len(response['response']['docs']) > 0:
-      <div class="btn-group download-btn-group" style="margin-left: 15px">
-        <button type="button" id="download-btn" class="btn btn-inverse dropdown-toggle" data-toggle="dropdown"><i class="fa fa-download"></i></button>
-        <ul class="dropdown-menu" role="menu">
-          <li><a href="javascript:void(0)" id="download-xls"><i class="hfo hfo-file-xls"></i>&nbsp; ${ _('XLS') }</a></li>
-          <li><a href="javascript:void(0)" id="download-csv"><i class="hfo hfo-file-csv">&nbsp; ${ _('CSV') }</i></a></li>
-        </ul>
-      </div>
-      % endif
+      <a class="btn" href="javascript:void(0)" data-bind="click: $root.query.addQ"><i class="fa fa-plus"></i></a>
+
+      <button type="submit" id="search-btn" class="btn btn-inverse" style="margin-left:10px"><i class="fa fa-search"></i></button>
     </div>
   </form>
 </div>
 
-% if 'is_demo' in response.get('responseHeader', {}):
-  <div class="container-fluid">
-    <div class="row-fluid">
-      <div class="span12">
-        <div class="alert alert-warn">
-          ${ _('A demo index is used. In order to be interactive, please ') } <a href="http://gethue.tumblr.com/post/78012277574/tutorial-demo-the-search-on-hadoop-examples" target="_blank">${ _('create the indexes') }</a> ${ _(' in Solr.') }
-        </div>
+<div class="card card-toolbar" data-bind="slideVisible: isEditing">
+  <div style="float: left">
+    <div class="toolbar-label">${_('LAYOUT')}</div>
+    <a href="javascript: oneThirdLeftLayout()" onmouseover="viewModel.previewColumns('oneThirdLeft')" onmouseout="viewModel.previewColumns('')">
+      <div class="layout-container">
+        <div class="layout-box" style="width: 24px"></div>
+        <div class="layout-box" style="width: 72px; margin-left: 4px"></div>
       </div>
-    </div>
+    </a>
+    <a href="javascript: fullLayout()" onmouseover="viewModel.previewColumns('full')" onmouseout="viewModel.previewColumns('')">
+      <div class="layout-container">
+        <div class="layout-box" style="width: 100px;"></div>
+      </div>
+    </a>
+    <a data-bind="visible: columns().length == 0" href="javascript: magicLayout(viewModel)" onmouseover="viewModel.previewColumns('magic')" onmouseout="viewModel.previewColumns('')">
+      <div class="layout-container">
+        <div class="layout-box" style="width: 100px;"><i class="fa fa-magic"></i></div>
+      </div>
+    </a>
   </div>
-% endif
 
+  <div style="float: left; margin-left: 20px" data-bind="visible: columns().length > 0">
+    <div class="toolbar-label">${_('WIDGETS')}</div>
+    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableResultset() },
+                    draggable: {data: draggableResultset(), isEnabled: availableDraggableResultset,
+                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
+                              'stop': function(event, ui){$('.card-body').slideDown('fast'); $root.collection.template.isGridLayout(true); }}}"
+         title="${_('Grid Results')}" rel="tooltip" data-placement="top">
+         <a data-bind="style: { cursor: $root.availableDraggableResultset() ? 'move' : 'default' }">
+                       <i class="fa fa-table"></i>
+         </a>
+    </div>
+    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableResultset() },
+                    draggable: {data: draggableHtmlResultset(), 
+                    isEnabled: availableDraggableResultset, 
+                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
+                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)}); $root.collection.template.isGridLayout(false); }}}"
+         title="${_('HTML Results')}" rel="tooltip" data-placement="top">
+         <a data-bind="style: { cursor: $root.availableDraggableResultset() ? 'move' : 'default' }">
+                       <i class="fa fa-code"></i>
+         </a>
+    </div>
+    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableChart() },
+                    draggable: {data: draggableFacet(), isEnabled: availableDraggableChart, 
+                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
+                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
+         title="${_('Text Facet')}" rel="tooltip" data-placement="top">
+         <a data-bind="style: { cursor: $root.availableDraggableChart() ? 'move' : 'default' }">
+                       <i class="fa fa-sort-amount-asc"></i>
+         </a>
+    </div>
+    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableChart() },
+                    draggable: {data: draggablePie(), isEnabled: availableDraggableChart, 
+                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
+                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
+         title="${_('Pie Chart')}" rel="tooltip" data-placement="top">
+         <a data-bind="style: { cursor: $root.availableDraggableChart() ? 'move' : 'default' }">
+                       <i class="hcha hcha-pie-chart"></i>
+         </a>
+    </div>
+    <!-- <div class="draggable-widget" data-bind="draggable: {data: draggableHit(), options: {'start': function(event, ui){$('.card-body').slideUp('fast');}, 'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}" title="${_('Hit Count')}" rel="tooltip" data-placement="top"><a data-bind="attr: {href: $root.availableDraggableResultset()}, css: {'btn-inverse': ! $root.availableDraggableResultset() }, style: { cursor: $root.availableDraggableResultset() ? 'move' : 'default' }"><i class="fa fa-tachometer"></i></a></div> -->
+    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableChart() },
+                    draggable: {data: draggableBar(), isEnabled: availableDraggableChart, 
+                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
+                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
+         title="${_('Bar Chart')}" rel="tooltip" data-placement="top">
+         <a data-bind="style: { cursor: $root.availableDraggableChart() ? 'move' : 'default' }">
+                       <i class="hcha hcha-bar-chart"></i>
+         </a>
+    </div>
+    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableNumbers() },
+                    draggable: {data: draggableLine(), isEnabled: availableDraggableNumbers, 
+                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
+                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
+         title="${_('Line')}" rel="tooltip" data-placement="top">
+         <a data-bind="style: { cursor: $root.availableDraggableNumbers() ? 'move' : 'default' }">
+                       <i class="hcha hcha-line-chart"></i>
+         </a>
+    </div>
+    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableHistogram() },
+                    draggable: {data: draggableHistogram(), isEnabled: availableDraggableHistogram, 
+                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
+                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
+         title="${_('Histogram')}" rel="tooltip" data-placement="top">
+         <a data-bind="style: { cursor: $root.availableDraggableHistogram() ? 'move' : 'default' }">
+                       <i class="hcha hcha-timeline-chart"></i>
+         </a>
+    </div>
+    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableFilter() },
+                    draggable: {data: draggableFilter(), isEnabled: availableDraggableFilter, 
+                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
+                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
+         title="${_('Filter Bar')}" rel="tooltip" data-placement="top">
+         <a data-bind="style: { cursor: $root.availableDraggableFilter() ? 'move' : 'default' }">
+                       <i class="fa fa-filter"></i>
+         </a>
+    </div>
+    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableChart() },
+                    draggable: {data: draggableMap(), isEnabled: availableDraggableChart, 
+                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
+                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
+         title="${_('Map')}" rel="tooltip" data-placement="top">
+         <a data-bind="style: { cursor: $root.availableDraggableChart() ? 'move' : 'default' }">
+                       <i class="hcha hcha-map-chart"></i>
+         </a>
+   </div>
+  </div>
+  <div class="clearfix"></div>
+</div>
 
-<div id="loader" class="row" style="text-align: center;margin-top: 20px">
-  <!--[if lte IE 9]>
-      <img src="/static/art/spinner-big.gif" />
-  <![endif]-->
-  <!--[if !IE]> -->
-    <i class="fa fa-spinner fa-spin" style="font-size: 60px; color: #DDD"></i>
-  <!-- <![endif]-->
+<div id="emptyDashboard" data-bind="visible: !isEditing() && columns().length == 0">
+  <div style="float:left; padding-top: 90px; margin-right: 20px; text-align: center; width: 260px">${_('Click on the pencil to get started with your dashboard!')}</div>
+  <img src="/search/static/art/hint_arrow.png" />
 </div>
 
-% if error:
-<div class="container-fluid">
-  <div class="row-fluid">
-    <div class="span12">
-      <div class="alert alert-error">
-        % if error['title']:
-        <h4>${ error['title'] }</h4><br/>
-        % endif
-        <span class="decodeError" data-message="${ error['message'] }"></span>
+
+<div data-bind="visible: isEditing() && previewColumns() != '' && columns().length == 0, css:{'with-top-margin': isEditing()}">
+  <div class="container-fluid">
+    <div class="row-fluid" data-bind="visible: previewColumns() == 'oneThirdLeft'">
+      <div class="span3 preview-row"></div>
+      <div class="span9 preview-row"></div>
+    </div>
+    <div class="row-fluid" data-bind="visible: previewColumns() == 'full'">
+      <div class="span12 preview-row">
+      </div>
+    </div>
+    <div class="row-fluid" data-bind="visible: previewColumns() == 'magic'">
+      <div class="span12 preview-row">
+        ${ _('Template predefined with some widgets.') }
       </div>
     </div>
   </div>
 </div>
-% else:
-<div class="container results">
-
-  <div id="mainContent" class="row hide">
-    % if response and 'response' in response and 'docs' in response['response'] and len(response['response']['docs']) > 0 and 'normalized_facets' in response:
-      <% shown_facets = 0 %>
-    <div class="span2 results">
-      <ul class="facet-list">
-        ## Force chart facets first
-        % for fld in response['normalized_facets']:
-          % if fld['type'] == 'chart':
-            <%
-            found_value = ""
-            for fq in solr_query['fq'].split('|'):
-              if fq and fq.split(':')[0] == fld['field']:
-                found_value = fq[fq.find(":") + 1:]
-                remove_list = solr_query['fq'].split('|')
-                remove_list.remove(fq)
-            %>
-            %if found_value != "":
-              <% shown_facets += 1 %>
-              <li class="nav-header">${fld['label']}</li>
-              <li><strong>${ found_value }</strong> <a href="?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${utf_quoter('|'.join(remove_list))}${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}"><i class="fa fa-times"></i></a></li>
-            %endif
-          % endif
-        % endfor
-        % for fld in response['normalized_facets']:
-          % if fld['type'] != 'chart':
-            <% shown_facets += 1 %>
-            % if fld['type'] == 'date':
-              <li class="nav-header facetHeader dateFacetHeader">${fld['label']}</li>
-            % else:
-              <li class="nav-header facetHeader">${fld['label']}</li>
-            % endif
-
-            <%
-            found_value = ""
-            for fq in solr_query['fq'].split('|'):
-              if fq and fq.split(':')[0] == fld['field']:
-                found_value = fq[fq.find(":") + 1:]
-                remove_list = solr_query['fq'].split('|')
-                remove_list.remove(fq)
-            %>
-            % for group, count in macros.pairwise(fld['counts']):
-              % if count > 0 and group != "" and found_value == "" and loop.index < 100:
-                % if fld['type'] == 'field':
-                  <li class="facetItem"><a href='?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${ utf_quoter(solr_query['fq']) }|${ fld['field'] }:"${utf_quoter(group)}"${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}'>${group}</a> <span class="counter">(${ count })</span></li>
-                % endif
-                % if fld['type'] == 'range':
-                  <li class="facetItem"><a href='?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${ utf_quoter(solr_query['fq']) }|${ fld['field'] }:["${ group }" TO "${ str(int(group) + int(fld['gap']) - 1) }"]${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}'>${ group } - ${ str(int(group) + int(fld['gap']) - 1) }</a> <span class="counter">(${ count })</span></li>
-                % endif
-                % if fld['type'] == 'date':
-                  <li class="facetItem dateFacetItem"><a href='?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${ utf_quoter(solr_query['fq']) }|${ fld['field'] }:[${ group } TO ${ group }${ utf_quoter(fld['gap']) }]${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}'><span class="dateFacet" data-format="${fld['format']}">${ group }<span class="dateFacetGap hide">${ fld['gap'] }</span></span></a> <span class="counter">(${ count })</span></li>
-                % endif
-              % endif
-              % if found_value != "" and loop.index < 100:
-                % if fld['type'] == 'field' and '"' + group + '"' == found_value:
-                  <li class="facetItem"><strong>${ group }</strong> <a href="?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${utf_quoter('|'.join(remove_list))}${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}"><i class="fa fa-times"></i></a></li>
-                % endif
-                % if fld['type'] == 'range' and '["' + group + '" TO "' + str(int(group) + int(fld['gap']) - 1) + '"]' == found_value:
-                  <li class="facetItem"><strong>${ group } - ${ str(int(group) + int(fld['gap']) - 1) }</strong> <a href="?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${utf_quoter('|'.join(remove_list))}${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}"><i class="fa fa-times"></i></a></li>
-                % endif
-                % if fld['type'] == 'date' and found_value.startswith('[' + group + ' TO'):
-                  <li class="facetItem"><strong><span class="dateFacet" data-format="${fld['format']}">${ group }<span class="dateFacetGap hide">${ fld['gap'] }</span></span></strong> <a href="?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${utf_quoter('|'.join(remove_list))}${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}"><i class="fa fa-times"></i></a></li>
-                % endif
-              % endif
-            % endfor
-          % endif
-        % endfor
-      </ul>
+
+<div data-bind="css: {'dashboard': true, 'with-top-margin': isEditing()}">
+  <div class="container-fluid">
+    <div class="row-fluid" data-bind="template: { name: 'column-template', foreach: columns}">
+    </div>
+    <div class="clearfix"></div>
+  </div>
+</div>
+
+<script type="text/html" id="column-template">
+  <div data-bind="css: klass">
+    <div class="container-fluid" data-bind="visible: $root.isEditing">
+      <div data-bind="css: {'add-row': true, 'is-editing': $root.isEditing}, sortable: { data: drops, isEnabled: $root.isEditing, options: {'placeholder': 'add-row-highlight', 'greedy': true, 'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}, dragged: function(widget){var _r = $data.addEmptyRow(true); _r.addWidget(widget);$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});showAddFacetDemiModal(widget);viewModel.search()}}"></div>
+    </div>
+    <div data-bind="template: { name: 'row-template', foreach: rows}">
+    </div>
+    <div class="container-fluid" data-bind="visible: $root.isEditing">
+      <div data-bind="css: {'add-row': true, 'is-editing': $root.isEditing}, sortable: { data: drops, isEnabled: $root.isEditing, options: {'placeholder': 'add-row-highlight', 'greedy': true, 'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}, dragged: function(widget){var _r = $data.addEmptyRow(); _r.addWidget(widget);$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});showAddFacetDemiModal(widget);viewModel.search()}}"></div>
+    </div>
+  </div>
+</script>
+
+<script type="text/html" id="row-template">
+  <div class="emptyRow" data-bind="visible: widgets().length == 0 && $index() == 0 && $root.isEditing() && $parent.size() > 4 && $parent.rows().length == 1">
+    <img src="/search/static/art/hint_arrow_flipped.png" style="float:left; margin-right: 10px"/>
+    <div style="float:left; text-align: center; width: 260px">${_('Drag any of the widgets inside your empty row')}</div>
+    <div class="clearfix"></div>
+  </div>
+  <div class="container-fluid">
+    <div class="row-header" data-bind="visible: $root.isEditing">
+      <span class="muted">${_('Row')}</span>
+      <div style="display: inline; margin-left: 60px">
+        <a href="javascript:void(0)" data-bind="visible: $index()<$parent.rows().length-1, click: function(){moveDown($parent, this)}"><i class="fa fa-chevron-down"></i></a>
+        <a href="javascript:void(0)" data-bind="visible: $index()>0, click: function(){moveUp($parent, this)}"><i class="fa fa-chevron-up"></i></a>
+        <a href="javascript:void(0)" data-bind="visible: $parent.rows().length > 1, click: function(){remove($parent, this)}"><i class="fa fa-times"></i></a>
+      </div>
+    </div>
+    <div data-bind="css: {'row-fluid': true, 'row-container':true, 'is-editing': $root.isEditing},
+        sortable: { template: 'widget-template', data: widgets, isEnabled: $root.isEditing, 
+        options: {'handle': '.move-widget', 'opacity': 0.7, 'placeholder': 'row-highlight', 'greedy': true, 
+            'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}, 
+            'helper': function(event){lastWindowScrollPosition = $(window).scrollTop(); $('.card-body').slideUp('fast'); var _par = $('<div>');_par.addClass('card card-widget');var _title = $('<h2>');_title.addClass('card-heading simple');_title.text($(event.toElement).text());_title.appendTo(_par);_par.height(80);_par.width(180);return _par;}},
+            dragged: function(widget){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});showAddFacetDemiModal(widget);viewModel.search()}}">
+    </div>
+  </div>
+</script>
+
+<script type="text/html" id="widget-template">
+  <div data-bind="attr: {'id': 'wdg_'+ id(),}, css: klass">
+    <h2 class="card-heading simple">
+      <span data-bind="visible: $root.isEditing">
+        <a href="javascript:void(0)" class="move-widget"><i class="fa fa-arrows"></i></a>
+        <a href="javascript:void(0)" data-bind="click: compress, visible: size() > 1"><i class="fa fa-step-backward"></i></a>
+        <a href="javascript:void(0)" data-bind="click: expand, visible: size() < 12"><i class="fa fa-step-forward"></i></a>
+        &nbsp;
+      </span>
+      <span data-bind="with: $root.collection.getFacetById(id())">
+        <span data-bind="editable: label, editableOptions: {enabled: $root.isEditing()}"></span>
+      </span>
+      <!-- ko ifnot: $root.collection.getFacetById(id()) -->
+        <span data-bind="editable: name, editableOptions: {enabled: $root.isEditing()}"></span>
+      <!-- /ko -->
+      <div class="inline pull-right" data-bind="visible: $root.isEditing">
+        <a href="javascript:void(0)" data-bind="click: function(){remove($parent, this)}"><i class="fa fa-times"></i></a>
+      </div>
+    </h2>
+    <div class="card-body" style="padding: 5px;">    
+      <div data-bind="template: { name: function() { return widgetType(); } }" class="widget-main-section"></div>
     </div>
-    % endif
-
-    % if response and 'response' in response and 'docs' in response['response'] and len(response['response']['docs']) > 0:
-      % if response['normalized_facets'] and shown_facets > 0:
-      <div class="span10 results">
-      % else:
-      <div class="span12 results">
-      % endif
-      <ul class="breadcrumb">
-        <li class="pull-right">
-          <div id="sortBy" style="display: inline" class="dropdown">
-            Sort by <a data-toggle="dropdown" href="#"><strong></strong> <i class="fa fa-caret-down"></i></a>
-            <ul class="dropdown-menu">
-            </ul>
+  </div>
+</script>
+
+<script type="text/html" id="empty-widget">
+  ${ _('This is an empty widget.')}
+</script>
+
+
+<script type="text/html" id="hit-widget">
+  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
+
+  <!-- /ko -->
+
+  <!-- ko if: $root.getFacetFromQuery(id()) -->
+  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
+    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">      
+      ${ _('Label') }: <input type="text" data-bind="value: label" />
+    </div>  
+
+    <span data-bind="text: query" />: <span data-bind="text: count" />
+  </div>
+  <!-- /ko -->
+</script>
+
+<script type="text/html" id="facet-toggle">
+    <!-- ko if: type() == 'range' -->
+      ${ _('Start') }:
+      <input type="text" class="input-large" data-bind="value: properties.start" />
+      <br/>
+      ${ _('End') }: <input type="text" class="input-large" data-bind="value: properties.end" />
+      <br/>
+      ${ _('Gap') }: <input type="text" class="input-small" data-bind="value: properties.gap" />
+      <br/>
+      ${ _('Min') }:
+      <input type="text" class="input-medium" data-bind="value: properties.min" />
+      <br/>
+      ${ _('Max') }: <input type="text" class="input-medium" data-bind="value: properties.max" />
+      <br/>      
+    <!-- /ko -->
+    <!-- ko if: type() == 'field' -->
+      ${ _('Limit') }: <input type="text" class="input-medium" data-bind="value: properties.limit" />
+    <!-- /ko -->
+
+    <a href="javascript: void(0)" class="btn btn-loading" data-bind="visible: properties.canRange, click: $root.collection.toggleRangeFacet" data-loading-text="...">
+      <i class="fa" data-bind="css: { 'fa-arrows-h': type() == 'range', 'fa-circle': type() == 'field' }, attr: { title: type() == 'range' ? 'Range' : 'Term' }"></i>
+    </a>
+    <a href="javascript: void(0)" class="btn btn-loading" data-bind="click: $root.collection.toggleSortFacet" data-loading-text="...">          
+      <i class="fa" data-bind="css: { 'fa-caret-down': properties.sort() == 'desc', 'fa-caret-up': properties.sort() == 'asc' }"></i>
+    </a>
+</script>
+
+<script type="text/html" id="facet-widget">
+  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
+  <!-- /ko -->
+
+  <div class="widget-spinner" data-bind="visible: isLoading()">
+    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
+  </div>
+
+  <!-- ko if: $root.getFacetFromQuery(id()) -->
+  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
+    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">
+      <span data-bind="template: { name: 'facet-toggle', afterRender: function(){ $root.getWidgetById($parent.id).isLoading(false); } }">
+      </span>
+    </div>
+    <div data-bind="with: $root.collection.getFacetById($parent.id())">
+	    <!-- ko if: type() != 'range' -->
+        <div data-bind="foreach: $parent.counts">
+          <div>
+            <a href="javascript: void(0)">              
+              <!-- ko if: $index() != $parent.properties.limit() -->
+                <!-- ko if: ! $data.selected -->
+                  <span data-bind="text: $data.value, click: function(){ $root.query.toggleFacet({facet: $data, widget_id: $parent.id()}) }"></span>
+                  <span class="counter" data-bind="text: ' (' + $data.count + ')', click: function(){ $root.query.toggleFacet({facet: $data, widget_id: $parent.id()}) }"></span>                
+                <!-- /ko -->
+                <!-- ko if: $data.selected -->
+                  <span data-bind="click: function(){ $root.query.toggleFacet({facet: $data, widget_id: $parent.id()}) }">
+                    <span data-bind="text: $data.value"></span>
+                    <i class="fa fa-times"></i>
+                  </span>
+                <!-- /ko -->
+              <!-- /ko -->
+              <!-- ko if: $index() == $parent.properties.limit() -->
+                <!-- ko if: $parent.properties.prevLimit == undefined || $parent.properties.prevLimit == $parent.properties.limit() -->
+                  <span data-bind="click: function(){ $root.collection.upDownFacetLimit($parent.id(), 'up') }">
+                    ${ _('Show more...') }
+                  </span>
+                <!-- /ko -->
+                <!-- ko if: $parent.properties.prevLimit != undefined && $parent.properties.prevLimit != $parent.properties.limit() -->
+                  <span data-bind="click: function(){ $root.collection.upDownFacetLimit($parent.id(), 'up') }">
+                    ${ _('Show more') }
+                  </span> 
+                  /             
+                  <span data-bind="click: function(){ $root.collection.upDownFacetLimit($parent.id(), 'down') }">
+                    ${ _('less...') }
+                  </span>                    
+                </span>
+                <!-- /ko -->
+              <!-- /ko -->
+            </a>
           </div>
-        </li>
-        <li class="active">
-        <%
-          end_record = int(solr_query["start"])+int(solr_query["rows"])
-          if end_record > int(response['response']['numFound']):
-            end_record = response['response']['numFound'];
-        %>
-          ${_('Page %s of %s. Showing %s results (%s seconds)') % (solr_query["current_page"], solr_query["total_pages"], response['response']['numFound'], float(solr_query["search_time"])/1000)}
-        </li>
+        </div>
+	    <!-- /ko -->
+	    <!-- ko if: type() == 'range' -->
+        <div data-bind="foreach: $parent.counts">
+          <div>
+            <a href="javascript: void(0)">
+              <!-- ko if: ! selected --> 
+                <span data-bind="click: function(){ $root.query.selectRangeFacet({count: $data.value, widget_id: $parent.id(), from: $data.from, to: $data.to, cat: $data.field}) }">
+                  <span data-bind="text: $data.from + ' - ' + $data.to"></span>
+                  <span class="counter" data-bind="text: ' (' + $data.value + ')'"></span>
+                </span>
+              <!-- /ko -->
+              <!-- ko if: selected -->
+                <span data-bind="click: function(){ $root.query.selectRangeFacet({count: $data.value, widget_id: $parent.id(), from: $data.from, to: $data.to, cat: $data.field}) }">
+                  <span data-bind="text: $data.from + ' - ' + $data.to"></span>
+                  <i class="fa fa-times"></i>
+                </span>
+              <!-- /ko -->
+            </a>
+          </div>
+        </div>
+	    <!-- /ko -->    
+    </div>
+  </div>
+  <!-- /ko -->
+</script>
+
+<script type="text/html" id="resultset-widget">
+  <!-- ko if: $root.collection.template.isGridLayout() -->
+    <div style="float:left; margin-right: 10px" >
+      <div data-bind="visible: ! $root.collection.template.showFieldList()" style="padding-top: 5px; display: inline-block">
+        <a href="javascript: void(0)"  data-bind="click: function(){ $root.collection.template.showFieldList(true) }">
+          <i class="fa fa-chevron-right"></i>
+        </a>
+      </div>
+    </div>
+    <div data-bind="visible: $root.collection.template.showFieldList()" style="float:left; margin-right: 10px; background-color: #F6F6F6; padding: 5px">
+      <span data-bind="visible: $root.collection.template.showFieldList()">
+        <div>
+          <a href="javascript: void(0)" class="pull-right" data-bind="click: function(){ $root.collection.template.showFieldList(false) }">
+            <i class="fa fa-chevron-left"></i>
+          </a>
+          <input type="text" data-bind="value: $root.collection.template.fieldsAttributesFilter, valueUpdate:'afterkeydown'" placeholder="${_('Filter fields')}" style="width: 70%; margin-bottom: 10px" />
+        </div>
+        <div style="border-bottom: 1px solid #CCC; padding-bottom: 4px">
+          <a href="javascript: void(0)" class="btn btn-mini"
+            data-bind="click: toggleGridFieldsSelection, css: { 'btn-inverse': $root.collection.template.fields().length > 0 }"
+            style="margin-right: 2px;">
+            <i class="fa fa-square-o"></i>
+          </a>
+          <strong>${_('Field Name')}</strong>
+        </div>
+        <div class="fields-list" data-bind="foreach: $root.collection.template.filteredAttributeFields" style="max-height: 230px; overflow-y: auto; padding-left: 4px">
+          <label class="checkbox">
+            <input type="checkbox" data-bind="checkedValue: name, checked: $root.collection.template.fieldsSelected" />
+            <span data-bind="text: name"></span>
+          </label>
+        </div>
+      </span>
+    </div>
+
+    <div>
+      <div data-bind="visible: !$root.isRetrievingResults() && $root.results().length == 0">
+        ${ _('Your search did not match any documents.') }
+      </div>
+    
+      <!-- ko if: $root.response().response -->
+        <div data-bind="template: {name: 'resultset-pagination', data: $root.response() }"></div>
+      <!-- /ko -->
+      <div style="overflow-x: auto">
+        <table id="result-container" data-bind="visible: !$root.isRetrievingResults()" style="margin-top: 0; width: 100%">
+          <thead>
+            <tr data-bind="visible: $root.results().length > 0">
+              <th style="width: 18px">&nbsp;</th>
+              <!-- ko foreach: $root.collection.template.fieldsSelected -->
+              <th data-bind="with: $root.collection.getTemplateField($data), event: { mouseover: $root.enableGridlayoutResultChevron, mouseout: $root.disableGridlayoutResultChevron }" style="white-space: nowrap">
+                <div style="display: inline-block; width:20px;">
+                <a href="javascript: void(0)" data-bind="click: function(){ $root.collection.translateSelectedField($index(), 'left'); }">
+                    <i class="fa fa-chevron-left" data-bind="visible: $root.toggledGridlayoutResultChevron() && $index() > 0"></i>
+                    <i class="fa fa-chevron-left" style="color: #FFF" data-bind="visible: !$root.toggledGridlayoutResultChevron() || $index() == 0"></i>
+                </a>
+                </div>
+                <div style="display: inline-block;">
+                <a href="javascript: void(0)" title="${ _('Click to sort') }">
+                  <span data-bind="text: name, click: $root.collection.toggleSortColumnGridLayout"></span>
+                  <i class="fa" data-bind="visible: sort.direction() != null, css: { 'fa-chevron-down': sort.direction() == 'desc', 'fa-chevron-up': sort.direction() == 'asc' }"></i>
+                </a>
+                  </div>
+                <div style="display: inline-block; width:20px;">
+                <a href="javascript: void(0)" data-bind="click: function(){ $root.collection.translateSelectedField($index(), 'right'); }">
+                    <i class="fa fa-chevron-right" data-bind="visible: $root.toggledGridlayoutResultChevron() && $index() < $root.collection.template.fields().length - 1"></i>
+                  <i class="fa fa-chevron-up" style="color: #FFF" data-bind="visible: !$root.toggledGridlayoutResultChevron() || $index() == $root.collection.template.fields().length - 1,"></i>
+                </a>
+                </div>
+              </th>
+              <!-- /ko -->
+            </tr>
+            <tr data-bind="visible: $root.collection.template.fieldsSelected().length == 0">
+              <th style="width: 18px">&nbsp;</th>
+              <th>${ ('Document') }</th>
+            </tr>
+          </thead>
+          <tbody data-bind="foreach: { data: $root.results, as: 'documents' }" class="result-tbody">
+            <tr class="result-row" data-bind="attr: {'id': 'doc_' + $data['id']}">
+              <td><a href="javascript:void(0)" data-bind="click: toggleDocDetails"><i class="fa fa-caret-right"></i></a></td>
+              <!-- ko foreach: $data['row'] -->
+                <td data-bind="html: $data"></td>
+              <!-- /ko -->
+            </tr>
+          </tbody>
+        </table>
+      </div>
+      <div class="widget-spinner" data-bind="visible: $root.isRetrievingResults()">
+        <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+        <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
+      </div>	  
+    </div>
+  <!-- /ko -->
+</script>
+
+<script type="text/html" id="html-resultset-widget">
+  <!-- ko ifnot: $root.collection.template.isGridLayout() -->
+    <div data-bind="visible: $root.isEditing" style="margin-bottom: 20px">
+      <ul class="nav nav-pills">
+        <li class="active"><a href="javascript: void(0)" class="widget-editor-pill">${_('Editor')}</a></li>
+        <li><a href="javascript: void(0)" class="widget-html-pill">${_('HTML')}</a></li>
+        <li><a href="javascript: void(0)" class="widget-css-pill">${_('CSS & JS')}</a></li>
+        <li><a href="javascript: void(0)" class="widget-settings-pill">${_('Properties')}</a></li>
       </ul>
+    </div>
+
+    <!-- ko if: $root.isEditing() -->
+      <div class="widget-section widget-editor-section">
+        <div class="row-fluid">
+          <div class="span9">
+            <div data-bind="freshereditor: {data: $root.collection.template.template}"></div>
+          </div>
+          <div class="span3">
+            <h5 class="editor-title">${_('Available Fields')}</h5>
+            <select data-bind="options: $root.collection.fields, optionsText: 'name', value: $root.collection.template.selectedVisualField" class="input-large chosen-select"></select>
+            <button title="${ _('Click on this button to add the field') }" class="btn plus-btn" data-bind="click: $root.collection.template.addFieldToVisual">
+              <i class="fa fa-plus"></i>
+            </button>
 
-      % for fld in response['normalized_facets']:
-        %if fld['type'] == 'chart':
-          <%
-            values = ""
-            for group, count in macros.pairwise(fld['counts']):
-              values += "['" + group + "'," + str(count) + "],"
-          %>
-          <div class="chartComponent" data-values="[${values[:-1]}]" data-label="${fld['label']}" data-field="${fld['field']}" data-gap="${'gap' in fld and fld['gap'] or ''}">
-            <!--[if lte IE 9]>
-              <img src="/static/art/spinner-big.gif" />
-            <![endif]-->
-            <!--[if !IE]> -->
-              <i class="fa fa-spinner fa-spin" style="font-size: 24px; color: #DDD"></i>
-            <!-- <![endif]-->
+            <h5 class="editor-title" style="margin-top: 30px">${_('Available Functions')}</h2>
+            <select id="visualFunctions" data-bind="value: $root.collection.template.selectedVisualFunction" class="input-large chosen-select">
+              <option title="${ _('Formats date or timestamp in DD-MM-YYYY') }" value="{{#date}} {{/date}}">{{#date}}</option>
+              <option title="${ _('Formats date or timestamp in HH:mm:ss') }" value="{{#time}} {{/time}}">{{#time}}</option>
+              <option title="${ _('Formats date or timestamp in DD-MM-YYYY HH:mm:ss') }" value="{{#datetime}} {{/datetime}}">{{#datetime}}</option>
+              <option title="${ _('Formats a date in the full format') }" value="{{#fulldate}} {{/fulldate}}">{{#fulldate}}</option>
+              <option title="${ _('Formats a date as a Unix timestamp') }" value="{{#timestamp}} {{/timestamp}}">{{#timestamp}}</option>
+              <option title="${ _('Formats a Unix timestamp as Ns, Nmin, Ndays... ago') }" value="{{#fromnow}} {{/fromnow}}">{{#fromnow}}</option>
+              <option title="${ _('Downloads and embed the file in the browser') }" value="{{#embeddeddownload}} {{/embeddeddownload}}">{{#embeddeddownload}}</option>
+              <option title="${ _('Downloads the linked file') }" value="{{#download}} {{/download}}">{{#download}}</option>
+              <option title="${ _('Preview file in File Browser') }" value="{{#preview}} {{/preview}}">{{#preview}}</option>
+              <option title="${ _('Truncate a value after 100 characters') }" value="{{#truncate100}} {{/truncate100}}">{{#truncate100}}</option>
+              <option title="${ _('Truncate a value after 250 characters') }" value="{{#truncate250}} {{/truncate250}}">{{#truncate250}}</option>
+              <option title="${ _('Truncate a value after 500 characters') }" value="{{#truncate500}} {{/truncate500}}">{{#truncate500}}</option>
+            </select>
+            <button title="${ _('Click on this button to add the function') }" class="btn plus-btn" data-bind="click: $root.collection.template.addFunctionToVisual">
+              <i class="fa fa-plus"></i>
+            </button>
+            <p class="muted" style="margin-top: 10px"></p>
           </div>
-        %endif
-      % endfor
-
-      <script src="/static/ext/js/mustache.js"></script>
-
-      <div id="result-container"></div>
-
-      <textarea id="mustacheTmpl" class="hide">${ hue_collection.result.get_template(with_highlighting=True) | n,unicode }</textarea>
-      <script>
-
-        <%
-          docs = response['response']['docs']
-          for doc in response['response']['docs']:
-            # Beware, schema requires an 'id' field, silently do nothing
-            if 'id' in doc and doc['id'] in response.get('highlighting', []):
-              doc.update(response['highlighting'][doc['id']])
-        %>
-
-        var _mustacheTmpl = fixTemplateDotsAndFunctionNames($("#mustacheTmpl").text());
-        $.each(${ json.dumps([result for result in docs]) | n,unicode }, function (index, item) {
-          addTemplateFunctions(item);
-          $("<div>").addClass("result-row").html(
-            Mustache.render(_mustacheTmpl, item)
-          ).appendTo($("#result-container"));
-        });
-      </script>
-
-      <div class="pagination">
-        <ul>
-          <%
-            pages_to_show = 5 # always use an odd number since we do it symmetrically
-
-            beginning = 0
-            previous = int(solr_query["start"]) - int(solr_query["rows"])
-            next = int(solr_query["start"]) + int(solr_query["rows"])
-
-            pages_after = (pages_to_show - 1) / 2
-            pages_total = solr_query['total_pages']+1
-            real_pages_after =  pages_total - solr_query["current_page"]
-            symmetric_start = solr_query["current_page"] < pages_total - pages_after
-            symmetric_end = solr_query["current_page"] > pages_after
-
-            pagination_start = solr_query["current_page"] > (pages_to_show - 1)/2 and (symmetric_start and solr_query["current_page"] - (pages_to_show - 1)/2 or solr_query["current_page"] - pages_to_show + real_pages_after ) or 1
-            pagination_end = solr_query["current_page"] < solr_query['total_pages']+1-(pages_to_show - 1)/2 and (symmetric_end and solr_query["current_page"] + (pages_to_show - 1)/2 + 1 or solr_query["current_page"] + (pages_to_show - solr_query["current_page"]) + 1) or solr_query['total_pages']+1
-          %>
-          % if int(solr_query["start"]) > 0:
-            <li>
-              <a title="${_('Previous Page')}" href="?collection=${ current_collection }&query=${solr_query["q"]}&fq=${utf_quoter(solr_query["fq"])}${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}&rows=${solr_query["rows"]}&start=${previous}">${_('Previous Page')}</a>
-            </li>
-          % endif
-          % for page in range(pagination_start, pagination_end):
-            %if page > 0 and page < pages_total:
-            <li
-             %if solr_query["current_page"] == page:
-               class="active"
-             %endif
-                >
-              <a href="?collection=${ current_collection }&query=${solr_query["q"]}&fq=${utf_quoter(solr_query["fq"])}${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}&rows=${solr_query["rows"]}&start=${(int(page)-1)*int(solr_query["rows"])}">${page}</a>
-            </li>
-            %endif
-          % endfor
-          % if end_record < int(response["response"]["numFound"]):
-            <li>
-              <a title="Next page" href="?collection=${ current_collection }&query=${solr_query["q"]}&fq=${utf_quoter(solr_query["fq"])}${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}&rows=${solr_query["rows"]}&start=${next}">${_('Next Page')}</a>
-            </li>
-          % endif
-        </ul>
+        </div>
+      </div>
+      <div class="widget-section widget-html-section" style="display: none">
+        <div class="row-fluid">
+          <div class="span9">
+            <textarea data-bind="codemirror: {data: $root.collection.template.template, lineNumbers: true, htmlMode: true, mode: 'text/html' }" data-template="true"></textarea>
+          </div>
+          <div class="span3">
+            <h5 class="editor-title">${_('Available Fields')}</h2>
+            <select data-bind="options: $root.collection.fields, optionsText: 'name', value: $root.collection.template.selectedSourceField" class="input-medium chosen-select"></select>
+            <button title="${ _('Click on this button to add the field') }" class="btn plus-btn" data-bind="click: $root.collection.template.addFieldToSource">
+              <i class="fa fa-plus"></i>
+            </button>
+
+            <h5 class="editor-title" style="margin-top: 30px">${_('Available Functions')}</h2>
+            <select id="sourceFunctions" data-bind="value: $root.collection.template.selectedSourceFunction" class="input-medium chosen-select">
+              <option title="${ _('Formats a date in the DD-MM-YYYY format') }" value="{{#date}} {{/date}}">{{#date}}</option>
+              <option title="${ _('Formats a date in the HH:mm:ss format') }" value="{{#time}} {{/time}}">{{#time}}</option>
+              <option title="${ _('Formats a date in the DD-MM-YYYY HH:mm:ss format') }" value="{{#datetime}} {{/datetime}}">{{#datetime}}</option>
+              <option title="${ _('Formats a date in the full format') }" value="{{#fulldate}} {{/fulldate}}">{{#fulldate}}</option>
+              <option title="${ _('Formats a date as a Unix timestamp') }" value="{{#timestamp}} {{/timestamp}}">{{#timestamp}}</option>
+              <option title="${ _('Shows the relative time') }" value="{{#fromnow}} {{/fromnow}}">{{#fromnow}}</option>
+              <option title="${ _('Downloads and embed the file in the browser') }" value="{{#embeddeddownload}} {{/embeddeddownload}}">{{#embeddeddownload}}</option>
+              <option title="${ _('Downloads the linked file') }" value="{{#download}} {{/download}}">{{#download}}</option>
+              <option title="${ _('Preview file in File Browser') }" value="{{#preview}} {{/preview}}">{{#preview}}</option>
+              <option title="${ _('Truncate a value after 100 characters') }" value="{{#truncate100}} {{/truncate100}}">{{#truncate100}}</option>
+              <option title="${ _('Truncate a value after 250 characters') }" value="{{#truncate250}} {{/truncate250}}">{{#truncate250}}</option>
+              <option title="${ _('Truncate a value after 500 characters') }" value="{{#truncate500}} {{/truncate500}}">{{#truncate500}}</option>
+            </select>
+            <button title="${ _('Click on this button to add the function') }" class="btn plus-btn" data-bind="click: $root.collection.template.addFunctionToSource">
+              <i class="fa fa-plus"></i>
+            </button>
+            <p class="muted" style="margin-top: 10px"></p>
+          </div>
+        </div>
+      </div>
+      <div class="widget-section widget-css-section" style="display: none">
+        <textarea data-bind="codemirror: {data: $root.collection.template.extracode, lineNumbers: true, htmlMode: true, mode: 'text/html' }"></textarea>
+      </div>
+      <div class="widget-section widget-settings-section" style="display: none, min-height:200px">
+        ${ _('Sorting') }
+        
+        <div data-bind="foreach: $root.collection.template.fieldsSelected">
+          <span data-bind="text: $data"></span>
+        </div>
+        <br/>  
+      </div>
+    <!-- /ko -->
+
+    <div style="overflow-x: auto">
+      <div data-bind="visible: $root.results().length == 0">
+        ${ _('Your search did not match any documents.') }
+      </div>
+    
+      <!-- ko if: $root.response().response -->
+        <div data-bind="template: {name: 'resultset-pagination', data: $root.response() }"></div>
+      <!-- /ko -->
+    
+      <div id="result-container" data-bind="foreach: $root.results">
+        <div class="result-row" data-bind="html: $data"></div>
+      </div>    
+    
+      <div class="widget-spinner" data-bind="visible: $root.isRetrievingResults()">
+        <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+        <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
       </div>
     </div>
-    % else:
-    <div class="span2">
-    </div>
-    <div class="span10">
-      <h4>
-        ${_('Your search')} - <strong>${solr_query["q"]}</strong> - ${_('did not match any documents.')}
-      </h4>
-      ${_('Suggestions:')}
-      <ul>
-        <li>${_('Make sure all words are spelled correctly.')}</li>
-        <li>${_('Try different keywords.')}</li>
-        <li>${_('Try more general keywords.')}</li>
-        <li>${_('Try fewer keywords.')}</li>
+  <!-- /ko -->
+</script>
+
+<script type="text/html" id="resultset-pagination">
+<div style="text-align: center; margin-top: 4px">
+  <a href="javascript: void(0)" title="${ _('Previous') }">
+    <span data-bind="text: name, click: $root.collection.toggleSortColumnGridLayout"></span>
+    <i class="fa fa-arrow-left" data-bind="
+        visible: $data.response.start * 1.0 >= $root.collection.template.rows() * 1.0,
+        click: function() { $root.query.paginate('prev') }">
+    </i></a>
+
+  ${ _('Showing') }
+  <span data-bind="text: ($data.response.start + 1)"></span>
+  ${ _('to') }
+  <span data-bind="text: ($data.response.start + $root.collection.template.rows())"></span>
+  ${ _('of') }
+  <span data-bind="text: $data.response.numFound"></span>
+  ${ _(' results.') }
+
+  ${ _('Show') }
+  <span data-bind="visible: $root.isEditing()" class="spinedit-pagination">
+    <input type="text" data-bind="spinedit: $root.collection.template.rows, valueUpdate:'afterkeydown'" style="text-align: center; margin-bottom: 0" />
+  </span>
+  ${ _('results per page.') }
+
+
+  <a href="javascript: void(0)" title="${ _('Next') }">
+    <span data-bind="text: name, click: $root.collection.toggleSortColumnGridLayout"></span>
+    <i class="fa fa-arrow-right" data-bind="
+        visible: ($root.collection.template.rows() * 1.0 + $data.response.start * 1.0) < $data.response.numFound,
+        click: function() { $root.query.paginate('next') }">
+    </i>
+  </a>  
+
+  <!-- ko if: $data.response.numFound > 0 && $data.response.numFound <= 1000 -->
+  <span class="pull-right">
+    <form method="POST" action="${ url('search:download') }">
+      <input type="hidden" name="collection" data-bind="value: ko.mapping.toJSON($root.collection)"/>
+      <input type="hidden" name="query" data-bind="value: ko.mapping.toJSON($root.query)"/>
+      <button class="btn" type="submit" name="json" title="${ _('Download as JSON') }"><i class="hfo hfo-file-json"></i></button>
+      <button class="btn" type="submit" name="csv" title="${ _('Download as CSV') }"><i class="hfo hfo-file-csv"></i></button>
+      <button class="btn" type="submit" name="xls" title="${ _('Download as Excel') }"><i class="hfo hfo-file-xls"></i></button>
+    </form>
+  </span>
+  <!-- /ko -->
+</div>
+</script>
+
+<script type="text/html" id="histogram-widget">
+  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
+  <!-- /ko -->
+
+  <div class="widget-spinner" data-bind="visible: isLoading()">
+    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
+  </div>
+
+  <!-- ko if: $root.getFacetFromQuery(id()) -->
+  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
+    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">      
+      <span data-bind="template: { name: 'facet-toggle' }">
+      </span>
+    </div>  
+
+    <a href="javascript:void(0)" data-bind="click: $root.collection.timeLineZoom"><i class="fa fa-search-minus"></i></a>
+    <span>
+      ${ _('Group By') }
+      <select class="input-medium" data-bind="options: $root.query.multiqs, optionsValue: 'id',optionsText: 'label', value: $root.query.selectedMultiq">
+      </select>      
+    </span>
+
+    <div data-bind="timelineChart: {datum: {counts: counts, extraSeries: extraSeries, widget_id: $parent.id(), label: label}, stacked: $root.collection.getFacetById($parent.id()).properties.stacked(), field: field, label: label, transformer: timelineChartDataTransformer,
+      onSelectRange: function(from, to){ viewModel.collection.selectTimelineFacet({from: from, to: to, cat: field, widget_id: $parent.id()}) },
+      onStateChange: function(state){ $root.collection.getFacetById($parent.id()).properties.stacked(state.stacked); },
+      onClick: function(d){ viewModel.query.selectRangeFacet({count: d.obj.value, widget_id: $parent.id(), from: d.obj.from, to: d.obj.to, cat: d.obj.field}) },
+      onComplete: function(){ viewModel.getWidgetById(id).isLoading(false) }}" />
+  </div>
+  <!-- /ko -->
+</script>
+
+<script type="text/html" id="bar-widget">
+  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
+  <!-- /ko -->
+
+  <div class="widget-spinner" data-bind="visible: isLoading()">
+    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
+  </div>
+
+  <!-- ko if: $root.getFacetFromQuery(id()) -->
+  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
+    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">      
+      <span data-bind="template: { name: 'facet-toggle' }">
+      </span>
+    </div> 
+
+    <div data-bind="barChart: {datum: {counts: counts, widget_id: $parent.id(), label: label}, stacked: false, field: field, label: label,
+      transformer: barChartDataTransformer,
+      onStateChange: function(state){ console.log(state); },
+      onClick: function(d){ viewModel.query.selectRangeFacet({count: d.obj.value, widget_id: d.obj.widget_id, from: d.obj.from, to: d.obj.to, cat: d.obj.field}) },
+      onSelectRange: function(from, to){ viewModel.collection.selectTimelineFacet({from: from, to: to, cat: field, widget_id: $parent.id()}) },
+      onComplete: function(){ viewModel.getWidgetById(id).isLoading(false) } }"
+    />
+  </div>
+  <!-- /ko -->
+</script>
+
+<script type="text/html" id="line-widget">
+  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
+  <!-- /ko -->
+
+  <div class="widget-spinner" data-bind="visible: isLoading()">
+    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
+  </div>
+
+  <!-- ko if: $root.getFacetFromQuery(id()) -->
+  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
+    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">
+      <span data-bind="template: { name: 'facet-toggle' }">
+      </span>
+    </div>
+
+    <div data-bind="lineChart: {datum: {counts: counts, widget_id: $parent.id(), label: label}, field: field, label: label,
+      transformer: lineChartDataTransformer,      
+      onClick: function(d){ viewModel.query.selectRangeFacet({count: d.obj.value, widget_id: d.obj.widget_id, from: d.obj.from, to: d.obj.to, cat: d.obj.field}) },
+      onSelectRange: function(from, to){ viewModel.collection.selectTimelineFacet({from: from, to: to, cat: field, widget_id: $parent.id()}) },
+      onComplete: function(){ viewModel.getWidgetById(id).isLoading(false) } }"
+    />
+  </div>
+  <!-- /ko -->
+</script>
+
+
+<script type="text/html" id="pie-widget">
+  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
+  <!-- /ko -->
+
+  <!-- ko if: $root.getFacetFromQuery(id()) -->
+  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
+    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">
+      <span data-bind="template: { name: 'facet-toggle' }">
+      </span>
+    </div>
+
+    <div data-bind="with: $root.collection.getFacetById($parent.id())">
+      <!-- ko if: type() == 'range' -->
+      <div data-bind="pieChart: {data: {counts: $parent.counts, widget_id: $parent.id}, field: field, fqs: $root.query.fqs,
+        transformer: rangePieChartDataTransformer,
+        maxWidth: 250,
+        onClick: function(d){ viewModel.query.selectRangeFacet({count: d.data.obj.value, widget_id: d.data.obj.widget_id, from: d.data.obj.from, to: d.data.obj.to, cat: d.data.obj.field}) }, 
+        onComplete: function(){ viewModel.getWidgetById($parent.id).isLoading(false)} }" />
+      <!-- /ko -->
+      <!-- ko if: type() != 'range' -->
+      <div data-bind="pieChart: {data: {counts: $parent.counts, widget_id: $parent.id}, field: field, fqs: $root.query.fqs,
+        transformer: pieChartDataTransformer,
+        maxWidth: 250,
+        onClick: function(d){viewModel.query.toggleFacet({facet: d.data.obj, widget_id: d.data.obj.widget_id})},
+        onComplete: function(){viewModel.getWidgetById($parent.id).isLoading(false)}}" />
+      <!-- /ko -->
+    </div>    
+  </div>
+  <!-- /ko -->
+  <div class="widget-spinner" data-bind="visible: isLoading()">
+    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
+  </div>
+</script>
+
+<script type="text/html" id="filter-widget">
+  <div data-bind="visible: $root.query.fqs().length == 0" style="margin-top: 10px">${_('There are currently no filters applied.')}</div>
+  <div data-bind="foreach: { data: $root.query.fqs, afterRender: function(){ isLoading(false); } }">
+    <!-- ko if: $data.type() == 'field' -->
+    <div class="filter-box">
+      <a href="javascript:void(0)" class="pull-right" data-bind="click: function(){ viewModel.query.removeFilter($data); viewModel.search() }"><i class="fa fa-times"></i></a>
+      <strong>${_('field')}</strong>:
+      <span data-bind="text: $data.field"></span>
+      <br/>
+      <strong>${_('value')}</strong>:
+      <span data-bind="text: $data.filter"></span>
+    </div>
+    <!-- /ko -->
+    <!-- ko if: $data.type() == 'range' -->
+    <div class="filter-box">
+      <a href="javascript:void(0)" class="pull-right" data-bind="click: function(){ viewModel.query.removeFilter($data); viewModel.search() }"><i class="fa fa-times"></i></a>
+      <strong>${_('field')}</strong>:
+      <span data-bind="text: $data.field"></span>
+      <br/>
+      <span data-bind="foreach: $data.properties" style="font-weight: normal">
+        <strong>${_('from')}</strong>: <span data-bind="text: $data.from"></span>
+        <br/>
+        <strong>${_('to')}</strong>: <span data-bind="text: $data.from"></span>
+      </span>
+    </div>
+    <!-- /ko -->
+  </div>
+  <div class="clearfix"></div>
+  <div class="widget-spinner" data-bind="visible: isLoading() &&  $root.query.fqs().length > 0">
+    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
+  </div>
+</script>
+
+<script type="text/html" id="map-widget">
+  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
+  <!-- /ko -->
+
+  <!-- ko if: $root.getFacetFromQuery(id()) -->
+  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
+    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">
+      ${ _('Scope') }: 
+      <select data-bind="selectedOptions: properties.scope" class="input-small">
+        <option value="world">${ _("World") }</option>
+        <option value="usa">${ _("USA") }</option>
+      </select>
+      <span data-bind="template: { name: 'facet-toggle' }">
+      </span>
+    </div>
+    <div data-bind="with: $root.collection.getFacetById($parent.id())">
+      <div data-bind="mapChart: {data: {counts: $parent.counts, scope: $root.collection.getFacetById($parent.id).properties.scope()},
+        transformer: mapChartDataTransformer,
+        maxWidth: 750,
+        onClick: function(d){ viewModel.query.toggleFacet({facet: d, widget_id: $parent.id}) },
+        onComplete: function(){ viewModel.getWidgetById($parent.id).isLoading(false)} }" />
+    </div>
+  </div>
+  <!-- /ko -->
+  <div class="widget-spinner" data-bind="visible: isLoading()">
+    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
+  </div>
+</script>
+
+<div id="addFacetDemiModal" class="demi-modal hide" data-backdrop="false">
+  <div class="modal-body">
+    <a href="javascript: void(0)" data-dismiss="modal" data-bind="click: addFacetDemiModalFieldCancel" class="pull-right"><i class="fa fa-times"></i></a>
+    <div style="float: left; margin-right: 10px;text-align: center">
+      <input id="addFacetInput" type="text" data-bind="value: $root.collection.template.fieldsModalFilter, valueUpdate:'afterkeydown'" placeholder="${_('Filter fields')}" class="input" style="float: left" /><br/>
+    </div>
+    <div>
+      <ul data-bind="foreach: $root.collection.template.filteredModalFields().sort(function (l, r) { return l.name() > r.name() ? 1 : -1 }), visible: $root.collection.template.filteredModalFields().length > 0"
+          class="unstyled inline fields-chooser" style="height: 100px; overflow-y: auto">
+        <li data-bind="click: addFacetDemiModalFieldPreview">
+          <span class="badge badge-info"><span data-bind="text: name(), attr: {'title': type()}"></span>
+          </span>
+        </li>
       </ul>
+      <div class="alert alert-info inline" data-bind="visible: $root.collection.template.filteredModalFields().length == 0" style="margin-left: 124px;height: 42px;line-height: 42px">
+        ${_('There are no fields matching your search term.')}
+      </div>
     </div>
-    % endif
   </div>
 </div>
 
-% endif
+<div id="genericLoader" style="display: none">
+<!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
+<!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
+</div>
 
-% if hue_collection:
-  ${ hue_collection.result.get_extracode() | n,unicode }
-% endif
+<script id="document-details" type="x-tmpl-mustache">
+<div class="document-details">
+  <table>
+    <tbody>
+    {{#properties}}
+      <tr>
+        <th style="text-align: left; white-space: nobreak; vertical-align:top">{{key}}</th>
+        <td width="100%">{{value}}</td>
+      </tr>
+      {{/properties}}
+    </tbody>
+  </table>
+  </div>
+</script>
 
-<script>
-  $(document).ready(function () {
+## Extra code for style and custom JS
+<span data-bind="html: $root.collection.template.extracode"></span>
 
-    if ($(".errorlist").length > 0) {
-      $(".errorlist li").each(function () {
-        $(document).trigger("error", $(this).text());
-      });
-    }
+<link rel="stylesheet" href="/search/static/css/search.css">
+<link rel="stylesheet" href="/static/ext/css/hue-filetypes.css">
+<link rel="stylesheet" href="/static/ext/css/leaflet.css">
+<link rel="stylesheet" href="/static/ext/css/hue-charts.css">
+<link rel="stylesheet" href="/static/css/freshereditor.css">
+<link rel="stylesheet" href="/static/ext/css/codemirror.css">
+<link rel="stylesheet" href="/static/ext/css/bootstrap-editable.css">
+<link rel="stylesheet" href="/static/ext/css/bootstrap-slider.min.css">
+<link rel="stylesheet" href="/static/css/bootstrap-spinedit.css">
+<link rel="stylesheet" href="/static/ext/css/nv.d3.min.css">
+<link rel="stylesheet" href="/static/ext/chosen/chosen.min.css">
 
-    $(".decodeError").text($("<span>").html($(".decodeError").data("message")).text());
+<script src="/search/static/js/search.utils.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/knockout.mapping-2.3.2.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/knockout-sortable.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/bootstrap-editable.min.js"></script>
+<script src="/static/ext/js/bootstrap-slider.min.js"></script>
+<script src="/static/js/bootstrap-spinedit.js"></script>
+<script src="/static/js/ko.editable.js"></script>
+<script src="/static/ext/js/shortcut.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/freshereditor.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/codemirror-3.11.js"></script>
+<script src="/static/ext/js/moment.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/codemirror-xml.js"></script>
+<script src="/static/ext/js/mustache.js"></script>
+<script src="/static/ext/js/jquery/plugins/jquery-ui-1.10.4.draggable-droppable-sortable.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/jquery/plugins/jquery.flot.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/jquery/plugins/jquery.flot.categories.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/leaflet/leaflet.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/chosen/chosen.jquery.min.js" type="text/javascript" charset="utf-8"></script>
 
-    $("#loader").hide();
-    $("#mainContent").removeClass("hide");
-    window.onbeforeunload = function (e) {
-      $("#loader").show();
-      $("#mainContent").addClass("hide");
-    };
+<script src="/search/static/js/search.ko.js" type="text/javascript" charset="utf-8"></script>
 
-    var collectionProperties = ${ hue_collection.facets.data | n,unicode }.properties;
-    $(".facetHeader").each(function(cnt, section){
-      var _added = 0;
-      var _showMore = false;
-      var _lastSection = null;
-      $(section).nextUntil(".facetHeader").each(function(cnt, item){
-        if (cnt < collectionProperties.limit*1){ // it's a string, *1 -> number
-          $(item).show();
-          _added++;
-          if (cnt == (collectionProperties.limit*1) - 1){
-            _lastSection = $(item);
-          }
-        }
-        else {
-          _showMore = true;
-        }
-      });
-      if (_added == 0){
-        $(section).hide();
-      }
-      if (_showMore){
-        $("<li>").addClass("facetShowMore").html('<a href="javascript:void(0)">${_('Show')} ' + ($(section).nextUntil(".facetHeader").length-(collectionProperties.limit*1)) + ' ${_('more...')}</a>').insertAfter(_lastSection);
-      }
-    });
+<script src="/static/js/hue.geo.js"></script>
+<script src="/static/js/hue.colors.js"></script>
 
-    $(document).on("click", ".facetShowMore", function(){
-      $(this).hide();
-      $(this).nextUntil(".facetHeader").show();
-    });
+<script src="/static/ext/js/d3.v3.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/nv.d3.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/topojson.v1.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/topo/world.topo.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ext/js/topo/usa.topo.js" type="text/javascript" charset="utf-8"></script>
 
-    $(".dateFacet").each(function () {
-      var _m = moment($(this).text());
-      var _em = moment($(this).text());
-      var _format = $(this).data("format");
-      var _gap = $(this).find(".dateFacetGap").text();
-      var _how = _gap.match(/\d+/)[0];
-      var _what = _gap.substring(_how.length + 1).toLowerCase();
-      _em.add(_what, _how * 1);
-
-      if (_format != null && _format != "") {
-        if (_format.toLowerCase().indexOf("fromnow") > -1){
-          $(this).text(_m.fromNow() + " - " + _em.fromNow());
-        }
-        else {
-          $(this).text(_m.format(_format) + " - " + _em.format(_format));
-        }
-      }
-      else {
-        $(this).text(_m.format() + " - " + _em.format());
-      }
-      $(this).parents(".dateFacetItem").data("epoch", _m.valueOf());
-    });
+<script src="/search/static/js/nv.d3.datamaps.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/nv.d3.legend.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/nv.d3.multiBarWithBrushChart.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/nv.d3.lineWithBrushChart.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/nv.d3.growingDiscreteBar.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/nv.d3.growingDiscreteBarChart.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/nv.d3.growingMultiBar.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/nv.d3.growingMultiBarChart.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/nv.d3.growingPie.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/nv.d3.growingPieChart.js" type="text/javascript" charset="utf-8"></script>
+<script src="/search/static/js/charts.ko.js" type="text/javascript" charset="utf-8"></script>
 
-    var orderedDateFacets = $(".dateFacetItem");
-    orderedDateFacets.sort(function (a, b) {
-      a = $(a).data("epoch");
-      b = $(b).data("epoch");
-      if (a > b) {
-        return -1;
-      } else if (a < b) {
-        return 1;
-      } else {
-        return 0;
-      }
-    });
-    $(".dateFacetHeader").after(orderedDateFacets);
-
-    % if hue_collection:
-      $(".current-collection").text("${ hue_collection.label }");
-      $("#id_collection").val(${ hue_collection.id });
-
-      % if user.is_superuser:
-        var collectionUrl = $(".dropdown-collection[data-value=${ hue_collection.id }]").data("settings-url");
-        $(".change-settings").attr("href", collectionUrl);
-      % endif
-    % endif
-
-    $(document).on("click", ".dropdown-collection", function (e) {
-      e.preventDefault();
-      var collectionId = $(this).data("value");
-      $("select[name='collection']").val(collectionId);
-      % if user.is_superuser:
-        $(".change-settings").attr("href", $(this).data("settings-url"));
-      % endif
-      $("form").find("input[type='hidden']").val("");
-      $("form").submit();
-    });
+<script src="/static/ext/js/less-1.7.0.min.js" type="text/javascript" charset="utf-8"></script>
+
+<style type="text/css">
+  .dashboard .container-fluid {
+    padding: 6px;
+  }
+
+  .row-container {
+    width: 100%;
+    min-height: 70px;
+  }
 
-    $("#download-csv").on("click", function(e) {
-      $("form").attr('action', "${ url('search:download', format='csv') }");
-      $("form").attr('target', "_new");
-      $("form").submit();
-      $("form").removeAttr('action');
-      $("form").removeAttr('target');
+  .row-container.is-editing {
+    border: 1px solid #e5e5e5;
+  }
+
+  .ui-sortable {
+    background-color: #F3F3F3;
+    min-height: 100px;
+  }
+
+  .ui-sortable h2 {
+    padding-left: 10px!important;
+  }
+
+  .ui-sortable h2 ul {
+    float: left;
+    margin-right: 10px;
+    font-size: 14px;
+  }
+
+  .ui-sortable-disabled {
+    background-color: #FFF;
+  }
+
+  .card-column {
+    border: none;
+    min-height: 400px!important;
+  }
+
+  .card-widget {
+    padding-top: 0;
+    border: 0;
+    min-height: 100px;
+  }
+
+  .card-widget .card-heading {
+    font-size: 12px!important;
+    font-weight: bold!important;
+    line-height: 24px!important;
+  }
+
+  .card-widget .card-body {
+    margin-top: 0;
+  }
+
+  .card-toolbar {
+    margin: 0;
+    padding: 4px;
+    padding-top: 0;
+    top: 70px;
+    position: fixed;
+    width: 100%;
+    z-index: 1000;
+  }
+
+  .row-header {
+    background-color: #F6F6F6;
+    display: inline;
+    padding: 3px;
+    border: 1px solid #e5e5e5;
+    border-bottom: none;
+  }
+
+  .row-highlight {
+    background-color: #DDD;
+    min-height: 100px;
+  }
+
+  #emptyDashboard {
+    position: absolute;
+    right: 164px;
+    top: 80px;
+    color: #666;
+    font-size: 20px;
+  }
+
+  .emptyRow {
+    margin-top: 10px;
+    margin-left: 140px;
+    color: #666;
+    font-size: 18px;
+  }
+
+  .preview-row {
+    background-color: #DDD;
+    min-height: 400px!important;
+    margin-top: 30px;
+  }
+
+  .toolbar-label {
+    float: left;
+    font-weight: bold;
+    color: #999;
+    padding-left: 8px;
+    padding-top: 24px;
+  }
+
+  .draggable-widget {
+    width: 60px;
+    text-align: center;
+    float: left;
+    border: 1px solid #CCC;
+    margin-top: 10px;
+    margin-left: 10px;
+    cursor: move;
+  }
+
+  .draggable-widget.disabled {
+    cursor: default;
+  }
+
+  .draggable-widget a {
+    font-size: 28px;
+    line-height: 46px;
+  }
+
+  .draggable-widget.disabled a {
+    cursor: default;
+    color: #CCC;
+  }
+
+  .layout-container {
+    width: 100px;
+    float: left;
+    margin-top: 10px;
+    margin-left: 10px;
+  }
+
+  .layout-box {
+    float: left;
+    height: 48px;
+    background-color: #DDD;
+    text-align: center;
+  }
+
+  .layout-box i {
+    color: #333;
+    font-size: 28px;
+    line-height: 48px;
+  }
+
+  .layout-container:hover .layout-box {
+    background-color: #CCC;
+  }
+
+  .with-top-margin {
+    margin-top: 60px;
+  }
+
+  .ui-sortable .card-heading {
+    -webkit-touch-callout: none;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+  }
+
+  .search-bar {
+    padding-top: 6px;
+    padding-bottom: 6px;
+  }
+
+  .widget-settings-section {
+    display: none;
+  }
+
+  em {
+    font-weight: bold;
+    background-color: yellow;
+  }
+
+  .nvd3 .nv-brush .extent {
+    fill-opacity: .225!important;
+  }
+
+  .nvd3 .nv-legend .disabled rect {
+    fill-opacity: 0;
+  }
+
+
+  .fields-chooser li {
+    cursor: pointer;
+    margin-bottom: 10px;
+  }
+
+  .fields-chooser li .badge {
+    font-weight: normal;
+    font-size: 12px;
+  }
+
+  .widget-spinner {
+    padding: 10px;
+    font-size: 80px;
+    color: #CCC;
+    text-align: center;
+  }
+
+  .card {
+    margin: 0;
+  }
+
+  .badge-left {
+    border-radius: 9px 0px 0px 9px;
+    padding-right: 5px;
+  }
+
+  .badge-right {
+    border-radius: 0px 9px 9px 0px;
+    padding-left: 5px;
+  }
+
+  .trash-filter {
+    cursor: pointer;
+  }
+
+  .move-widget {
+    cursor: move;
+  }
+
+  body.modal-open {
+      overflow: auto!important;
+  }
+
+  .editable-click {
+    cursor: pointer;
+  }
+
+  .CodeMirror {
+    border: 1px dotted #DDDDDD;
+  }
+
+  [contenteditable=true] {
+    border: 1px dotted #DDDDDD;
+    outline: 0;
+    margin-top: 20px;
+    margin-bottom: 20px;
+    min-height: 150px;
+  }
+
+  [contenteditable=true] [class*="span"], .tmpl [class*="span"] {
+    background-color: #eee;
+    -webkit-border-radius: 3px;
+    -moz-border-radius: 3px;
+    border-radius: 3px;
+    min-height: 40px;
+    line-height: 40px;
+    background-color: #F3F3F3;
+    border: 2px dashed #DDD;
+  }
+
+  .tmpl {
+    margin: 10px;
+    height: 60px;
+  }
+
+  .tmpl [class*="span"] {
+    color: #999;
+    font-size: 12px;
+    text-align: center;
+    font-weight: bold;
+  }
+
+  .preview-row:nth-child(odd) {
+    background-color: #f9f9f9;
+  }
+
+  .editor-title {
+    font-weight: bold;
+    color: #262626;
+    border-bottom: 1px solid #338bb8;
+  }
+
+  .add-row {
+    background-color: #F6F6F6;
+    min-height: 36px;
+    border: 2px dashed #DDD;
+    text-align: center;
+    padding: 4px;
+  }
+
+  .add-row:before {
+    color:#DDD;
+    display: inline-block;
+    font-family: FontAwesome;
+    font-style: normal;
+    font-weight: normal;
+    font-size: 24px;
+    line-height: 1;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+    content: "\f055";
+  }
+
+  .add-row-highlight {
+    min-height: 10px;
+    background-color:#CCC;
+  }
+
+  .document-details {
+    background-color: #F6F6F6;
+    padding: 10px;
+    border: 1px solid #e5e5e5;
+  }
+
+  .result-row:nth-child(even) {
+    background-color: #F6F6F6;
+  }
+
+  .demi-modal {
+    min-height: 80px;
+  }
+
+  .filter-box {
+    float: left;
+    margin-right: 10px;
+    margin-bottom: 10px;
+    background-color: #F6F6F6;
+    padding: 5px;
+    border:1px solid #d8d8d8;
+    -webkit-border-radius: 3px;
+    -moz-border-radius: 3px;
+    border-radius: 3px;
+  }
+
+  .spinedit-pagination div.spinedit .fa-chevron-up {
+    top: -7px;
+  }
+
+  .spinedit-pagination div.spinedit .fa-chevron-down {
+    top: 7px;
+    left: -4px;
+  }
+
+</style>
+
+<script type="text/javascript" charset="utf-8">
+var viewModel;
+
+nv.dev = false;
+
+var lastWindowScrollPosition = 0;
+
+function pieChartDataTransformer(data) {
+  var _data = [];
+  $(data.counts).each(function (cnt, item) {
+    item.widget_id = data.widget_id;
+    _data.push({
+      label: item.value,
+      value: item.count,
+      obj: item
     });
-    $("#download-xls").on("click", function(e) {
-      $("form").attr('action', "${ url('search:download', format='xls') }");
-      $("form").attr('target', "_new");
-      $("form").submit();
-      $("form").removeAttr('action');
-      $("form").removeAttr('target');
+  });
+  return _data;
+}
+
+function rangePieChartDataTransformer(data) {
+  var _data = [];
+  $(data.counts).each(function (cnt, item) {
+    item.widget_id = data.widget_id;
+    _data.push({
+      label: item.from + ' - ' + item.to,
+      from: item.from,
+      to: item.to,
+      value: item.value,
+      obj: item
     });
+  });
+  return _data;
+}
 
-    function getCollectionPopoverContent() {
-      var _html = "<ul class='unstyled'>";
-      $("#collectionPopover ul li").each(function () {
-        if ($(this).find("a").data("value") != $("#id_collection").val()) {
-          _html += $(this).clone().wrap('<p>').parent().html();
-        }
+function barChartDataTransformer(rawDatum) {
+  var _datum = [];
+  var _data = [];
+  $(rawDatum.counts).each(function (cnt, item) {
+    item.widget_id = rawDatum.widget_id;
+    if (typeof item.from != "undefined"){
+      _data.push({
+        series: 0,
+        x: item.from,
+        x_end: item.to,
+        y: item.value,
+        obj: item
+      });
+    }
+    else {
+      _data.push({
+        series: 0,
+        x: item.value,
+        y: item.count,
+        obj: item
       });
-      _html += "</ul>";
-      return _html;
     }
+  });
+  _datum.push({
+    key: rawDatum.label,
+    values: _data
+  });
+  return _datum;
+}
 
-    $("#recordsPerPage").change(function () {
-      $("input[name='rows']").val($(this).val());
-      $("input[name='rows']").closest("form").submit();
-    });
-    $("#recordsPerPage").val($("input[name='rows']").val());
-
-    var sortingData = ${ hue_collection and hue_collection.sorting.data or '[]' | n,unicode };
-    if (sortingData && sortingData.fields && sortingData.fields.length > 0) {
-      $.each(sortingData.fields, function (index, item) {
-        var _dropDownOption= $("<li>");
-        _dropDownOption.html('<a href="#" class="dropdown-sort" data-field="'+ item.field +'" data-asc="'+ item.asc +'">'+ item.label +'</a>');
-        _dropDownOption.appendTo($("#sortBy .dropdown-menu"));
+function lineChartDataTransformer(rawDatum) {
+  var _datum = [];
+  var _data = [];
+  $(rawDatum.counts).each(function (cnt, item) {
+    item.widget_id = rawDatum.widget_id;
+    if (typeof item.from != "undefined"){
+      _data.push({
+        series: 0,
+        x: item.from,
+        x_end: item.to,
+        y: item.value,
+        obj: item
       });
-      var activeSorting = "${solr_query.get("sort", "")}";
-      if (activeSorting == ""){
-        // if the default sorting is just on one field, select that one
-        var _defaultSorting = "";
-        var _defaultSortingCnt = 0;
-        $.each(sortingData.fields, function (index, item) {
-          if (item.include) {
-            _defaultSorting = item.label;
-            _defaultSortingCnt++;
-          }
-        });
-        if (_defaultSortingCnt == 1){
-          $("#sortBy strong").text(_defaultSorting);
-        }
-      }
-      if (activeSorting != "" && activeSorting.indexOf(" ") > -1) {
-        $.each(sortingData.fields, function (index, item) {
-          if (item.field == activeSorting.split(" ")[0] && item.asc == (activeSorting.split(" ")[1] == "asc")) {
-            $("#sortBy strong").text(item.label);
-          }
-        });
-      }
     }
     else {
-      $("#sortBy").hide();
+      _data.push({
+        series: 0,
+        x: item.value,
+        y: item.count,
+        obj: item
+      });
     }
+  });
+  _datum.push({
+    key: rawDatum.label,
+    values: _data
+  });
+  return _datum;
+}
 
-    $(document).on("click", "#sortBy li a", function () {
-      var _this = $(this);
-      var _sort = _this.data("field") + "+" + (_this.data("asc") ? "asc" : "desc");
-      if (typeof _this.data("field") == "undefined") {
-        _sort = "";
-      }
-      location.href = "?collection=${ current_collection }&query=${solr_query["q"]}&fq=${solr_query["fq"]}&rows=${solr_query["rows"]}&start=${solr_query["start"]}" + (_sort != "" ? "&sort=" + _sort : "");
+function timelineChartDataTransformer(rawDatum) {
+  var _datum = [];
+  var _data = [];
+
+  $(rawDatum.counts).each(function (cnt, item) {
+    _data.push({
+      series: 0,
+      x: new Date(moment(item.from).valueOf()),
+      y: item.value,
+      obj: item
     });
+  });
+  
+  _datum.push({
+    key: rawDatum.label,
+    values: _data
+  });
+  
 
-    $("#id_query").focus();
+  // If multi query
+  $(rawDatum.extraSeries).each(function (cnt, item) {
+    if (cnt == 0) {
+      _datum = [];
+    }
+    var _data = [];
+    $(item.counts).each(function (cnt, item) {
+      _data.push({
+        series: cnt + 1,
+        x: new Date(moment(item.from).valueOf()),
+        y: item.value,
+        obj: item
+      });
+    });      
 
-    $(document).on("keydown", function (e) {
-      if (!e.ctrlKey && !e.altKey && !e.metaKey){
-        if (!$("#id_query").is(":focus")) {
-          $("#id_query").focus();
-          $("#id_query").val($("#id_query").val());
-        }
-      }
+    _datum.push({
+      key: item.label,
+      values: _data
     });
+  });
+  
+  return _datum;
+}
 
-    $("#id_query").on("click", function (e) {
-      if (e.pageX - $(this).position().left >= $(this).width()) {
-        $(this).val("");
-        $("#id_query").removeClass("deletable");
-      }
+function mapChartDataTransformer(data) {
+  var _data = [];
+  $(data.counts).each(function (cnt, item) {
+    _data.push({
+      label: item.value,
+      value: item.count,
+      obj: item
     });
+  });
+  return _data;
+}
 
-    $("#id_query").on("mousemove", function (e) {
-      if (e.pageX - $(this).position().left >= $(this).width() && $(this).hasClass("deletable")) {
-        $(this).css("cursor", "pointer");
-      }
-      else {
-        $(this).css("cursor", "auto");
-      }
-    });
+function toggleDocDetails(doc){
+  var _docRow = $("#doc_" + doc[viewModel.collection.idField()]);
+  if (_docRow.data("expanded") != null && _docRow.data("expanded")){
+    $("#doc_" + doc[viewModel.collection.idField()] + "_details").parent().hide();
+    _docRow.find(".fa-caret-down").removeClass("fa-caret-down").addClass("fa-caret-right");
+    _docRow.data("expanded", false);
+  }
+  else {
+    _docRow.data("expanded", true);
+    var _detailsRow = $("#doc_" + doc[viewModel.collection.idField()] + "_details");
+    if (_detailsRow.length > 0){
+      _detailsRow.parent().show();
+    }
+    else {
+      var _newRow = $("<tr>");
+      var _newCell = $("<td>").attr("colspan", _docRow.find("td").length).attr("id", "doc_" + doc[viewModel.collection.idField()] + "_details").html($("#genericLoader").html());
+      _newCell.appendTo(_newRow);
+      _newRow.insertAfter(_docRow);
+      viewModel.getDocument(doc);
+    }
+    _docRow.find(".fa-caret-right").removeClass("fa-caret-right").addClass("fa-caret-down");
+  }
+}
+
+function resizeFieldsList() {
+  $(".fields-list").css("max-height", Math.max($("#result-container").height(), 230));
+}
 
-    if ($("#id_query").val().trim() != "") {
-      $("#id_query").addClass("deletable");
+$(document).ready(function () {
+
+  var _resizeTimeout = -1;
+  $(window).resize(function(){
+    window.clearTimeout(_resizeTimeout);
+    window.setTimeout(function(){
+      resizeFieldsList();
+    }, 200);
+  });
+
+  $(document).on("showDoc", function(e, doc){
+    viewModel.collection.selectedDocument(doc);
+    var _docDetailsRow = $("#doc_" + doc[viewModel.collection.idField()] + "_details");
+    var _doc = {
+      properties: []
+    };
+    for (var i=0; i< Object.keys(doc).length; i++){
+      _doc.properties.push({
+        key: Object.keys(doc)[i],
+        value: doc[Object.keys(doc)[i]]
+      });
     }
+    var template = $("#document-details").html();
+    Mustache.parse(template);
+    var rendered = Mustache.render(template, _doc);
+    _docDetailsRow.html(rendered);
+  });
 
-    % if hue_collection:
-    $("#id_query").on("keyup", function() {
-      var query = $("#id_query").val();
-      if ($.trim(query) != "") {
-        $("#id_query").addClass("deletable");
+  $(document).on("click", ".widget-settings-pill", function(){
+    $(this).parents(".card-body").find(".widget-section").hide();
+    $(this).parents(".card-body").find(".widget-settings-section").show();
+    $(this).parent().siblings().removeClass("active");
+    $(this).parent().addClass("active");
+  });
+
+  $(document).on("click", ".widget-editor-pill", function(){
+    $(this).parents(".card-body").find(".widget-section").hide();
+    $(this).parents(".card-body").find(".widget-editor-section").show();
+    $(this).parent().siblings().removeClass("active");
+    $(this).parent().addClass("active");
+  });
+
+  $(document).on("click", ".widget-html-pill", function(){
+    $(this).parents(".card-body").find(".widget-section").hide();
+    $(this).parents(".card-body").find(".widget-html-section").show();
+    $(document).trigger("refreshCodemirror");
+    $(this).parent().siblings().removeClass("active");
+    $(this).parent().addClass("active");
+  });
+
+  $(document).on("click", ".widget-css-pill", function(){
+    $(this).parents(".card-body").find(".widget-section").hide();
+    $(this).parents(".card-body").find(".widget-css-section").show();
+    $(document).trigger("refreshCodemirror");
+    $(this).parent().siblings().removeClass("active");
+    $(this).parent().addClass("active");
+  });
+
+  ko.bindingHandlers.slideVisible = {
+    init: function (element, valueAccessor) {
+      var value = valueAccessor();
+      $(element).toggle(ko.unwrap(value));
+    },
+    update: function (element, valueAccessor) {
+      var value = valueAccessor();
+      ko.unwrap(value) ? $(element).slideDown(100) : $(element).slideUp(100);
+    }
+  };
+
+
+  ko.extenders.numeric = function (target, precision) {
+    var result = ko.computed({
+      read: target,
+      write: function (newValue) {
+        var current = target(),
+          roundingMultiplier = Math.pow(10, precision),
+          newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
+          valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
+
+        if (valueToWrite !== current) {
+          target(valueToWrite);
+        } else {
+          if (newValue !== current) {
+            target.notifySubscribers(valueToWrite);
+          }
+        }
       }
-      else {
-        $("#id_query").removeClass("deletable");
+    }).extend({ notify: 'always' });
+    result(target());
+    return result;
+  };
+
+  ko.bindingHandlers.freshereditor = {
+    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
+      var _el = $(element);
+      var options = $.extend(valueAccessor(), {});
+      _el.html(options.data());
+      _el.freshereditor({
+        excludes: ['strikethrough', 'removeFormat', 'insertorderedlist', 'justifyfull', 'insertheading1', 'insertheading2', 'superscript', 'subscript']
+      });
+      _el.freshereditor("edit", true);
+      _el.on("mouseup", function () {
+        storeSelection();
+        updateValues();
+      });
+
+      var sourceDelay = -1;
+      _el.on("keyup", function () {
+        clearTimeout(sourceDelay);
+        storeSelection();
+        sourceDelay = setTimeout(function () {
+          updateValues();
+        }, 100);
+      });
+
+      $(".chosen-select").chosen({
+        disable_search_threshold: 10,
+        width: "75%"
+      });
+
+      $(document).on("addFieldToVisual", function(e, field){
+        _el.focus();
+        pasteHtmlAtCaret("{{" + field.name() + "}}");
+      });
+
+      $(document).on("addFunctionToVisual", function(e, fn){
+        _el.focus();
+        pasteHtmlAtCaret(fn);
+      });
+
+      function updateValues(){
+        $("[data-template]")[0].editor.setValue(stripHtmlFromFunctions(_el.html()));
+        valueAccessor().data(_el.html());
       }
-    });
-    % endif
-
-    % if hue_collection.autocomplete:
-    $("#id_query").attr("autocomplete", "off");
-
-    $("#id_query").jHueDelayedInput(function(){
-      var query = $("#id_query").val();
-      if (query) {
-        $.ajax("${ url('search:query_suggest', collection_id=hue_collection.id) }" + query, {
-          type: 'GET',
-          success: function (data) {
-            if (data.message.spellcheck && ! jQuery.isEmptyObject(data.message.spellcheck.suggestions)) {
-              $('#id_query').typeahead({source: data.message.spellcheck.suggestions[1].suggestion});
-            }
+
+      function storeSelection() {
+        if (window.getSelection) {
+          // IE9 and non-IE
+          sel = window.getSelection();
+          if (sel.getRangeAt && sel.rangeCount) {
+            range = sel.getRangeAt(0);
+            _el.data("range", range);
           }
-        });
+        }
+        else if (document.selection && document.selection.type != "Control") {
+          // IE < 9
+          _el.data("selection", document.selection);
+        }
       }
-    });
-    % endif
-
-    function getFq(existing, currentField, currentValue) {
-      if (existing.indexOf(currentField) > -1) {
-        var _pieces = existing.split("|");
-        var _newPieces = [];
-        $(_pieces).each(function (cnt, item) {
-          if (item.indexOf(currentField) > -1) {
-            _newPieces.push(currentField + currentValue);
+
+    function pasteHtmlAtCaret(html) {
+      var sel, range;
+      if (window.getSelection) {
+        // IE9 and non-IE
+        sel = window.getSelection();
+        if (sel.getRangeAt && sel.rangeCount) {
+          if (_el.data("range")) {
+            range = _el.data("range");
           }
           else {
-            // !!! High trickery. Uses jquery to reconvert all html entities to text
-            _newPieces.push($("<span>").html(item).text());
+            range = sel.getRangeAt(0);
           }
-        });
-        return _newPieces.join("|");
-      }
-      else {
-        return $("<span>").html(existing).text() + "|" + currentField + currentValue;
+          range.deleteContents();
+
+          // Range.createContextualFragment() would be useful here but is
+          // non-standard and not supported in all browsers (IE9, for one)
+          var el = document.createElement("div");
+          el.innerHTML = html;
+          var frag = document.createDocumentFragment(), node, lastNode;
+          while ((node = el.firstChild)) {
+            lastNode = frag.appendChild(node);
+          }
+          range.insertNode(frag);
+
+          // Preserve the selection
+          if (lastNode) {
+            range = range.cloneRange();
+            range.setStartAfter(lastNode);
+            range.collapse(true);
+            sel.removeAllRanges();
+            sel.addRange(range);
+          }
+        }
+      } else if (document.selection && document.selection.type != "Control") {
+        // IE < 9
+        if (_el.data("selection")) {
+          _el.data("selection").createRange().pasteHTML(html);
+        }
+        else {
+          document.selection.createRange().pasteHTML(html);
+        }
       }
     }
+    }
+  };
 
-    var _chartData = null;
+  ko.bindingHandlers.slider = {
+    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
+      var _el = $(element);
+      var _options = $.extend(valueAccessor(), {});
+      _el.slider({
+        min: _options.min ? _options.min : 1,
+        max: _options.max ? _options.max : 10,
+        step: _options.step ? _options.step : 1,
+        handle: _options.handle ? _options.handle : 'circle',
+        value: _options.data(),
+        tooltip: 'always'
+      });
+      _el.on("slide", function (e) {
+        _options.data(e.value);
+      });
+    },
+    update: function (element, valueAccessor, allBindingsAccessor) {
+      var _options = $.extend(valueAccessor(), {});
+      $(element).slider("setValue", _options.data());
+    }
+  }
 
-    if ($(".chartComponent").length > 0){
-      _chartData = eval($(".chartComponent").data("values"));
+  ko.bindingHandlers.spinedit = {
+    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
+      $(element).spinedit({
+        minimum: 0,
+        maximum: 10000,
+        step: 5,
+        value: ko.unwrap(valueAccessor()),
+        numberOfDecimals: 0
+      });
+      $(element).on("valueChanged", function (e) {
+        valueAccessor()(e.value);
+      });
+    },
+    update: function (element, valueAccessor, allBindingsAccessor) {
+      $(element).spinedit("setValue", ko.unwrap(valueAccessor()));
     }
+  }
 
-    // test the content of _chartData to see if it can be rendered as chart
-    if (_chartData != null && _chartData.length > 0) {
-      if ($.isArray(_chartData[0])) {
-        if ($.isNumeric(_chartData[0][0]) || _chartData[0][0].match(/[0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]T/)) {
-          var _isDate = false;
-          if (_chartData[0][0].match(/[0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]T/) != null){
-            _isDate = true;
-          }
-          $(".chartComponent").jHueBlueprint({
-            data: _chartData,
-            label: $(".chartComponent").data("label"),
-            type: $.jHueBlueprint.TYPES.BARCHART,
-            color: $.jHueBlueprint.COLORS.BLUE,
-            isDateTime: _isDate,
-            fill: true,
-            enableSelection: true,
-            height: 100,
-            onSelect: function (range) {
-              var _start = Math.floor(range.xaxis.from)
-              var _end = Math.ceil(range.xaxis.to);
-              if (_isDate){
-                _start = moment(range.xaxis.from).utc().format("YYYY-MM-DD[T]HH:mm:ss[Z]");
-                _end = moment(range.xaxis.to).utc().format("YYYY-MM-DD[T]HH:mm:ss[Z]");
-              }
-              location.href = '?collection=${ current_collection }&query=${ solr_query['q'] }&fq=' + getFq("${ solr_query['fq'] }", $(".chartComponent").data("field"), ':["' + _start + '" TO "' + _end + '"]') + '${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}';
-            },
-            onItemClick: function (pos, item) {
-              if (item) {
-                $(".chartComponent").data("plotObj").highlight(item.series, item.datapoint);
-                var _point = item.datapoint[0];
-                if (_isDate){
-                  var _momentDate = moment(item.datapoint[0]);
-                  var _gap = $(".chartComponent").data("gap");
-                  if (_gap != null && _gap != ""){
-                    var _futureMomentDate = moment(item.datapoint[0]);
-                    var _how = _gap.match(/\d+/)[0];
-                    var _what = _gap.substring(_how.length + 1).toLowerCase();
-                    _futureMomentDate.add(_what, _how * 1);
-                    var _start = _momentDate.utc().format("YYYY-MM-DD[T]HH:mm:ss[Z]");
-                    var _end = _futureMomentDate.utc().format("YYYY-MM-DD[T]HH:mm:ss[Z]");
-                    location.href = '?collection=${ current_collection }&query=${ solr_query['q'] }&fq=' + getFq("${ solr_query['fq'] }", $(".chartComponent").data("field"), ':["' + _start + '" TO "' + _end + '"]') + '${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}';
-                  }
-                  else {
-                    _point = '"' + _momentDate.utc().format("YYYY-MM-DD[T]HH:mm:ss[Z]") + '"';
-                    location.href = '?collection=${ current_collection }&query=${ solr_query['q'] }&fq=' + getFq("${ solr_query['fq'] }", $(".chartComponent").data("field"), ':' + _point) + '${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}';
-                  }
-                }
-                else {
-                  location.href = '?collection=${ current_collection }&query=${ solr_query['q'] }&fq=' + getFq("${ solr_query['fq'] }", $(".chartComponent").data("field"), ':' + _point) + '${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}';
-                }
-              }
-            }
-          });
+  ko.bindingHandlers.codemirror = {
+    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
+      var options = $.extend(valueAccessor(), {});
+      var editor = CodeMirror.fromTextArea(element, options);
+      element.editor = editor;
+      editor.setValue(options.data());
+      editor.refresh();
+      var wrapperElement = $(editor.getWrapperElement());
+
+      $(document).on("refreshCodemirror", function(){
+        editor.setSize("100%", 300);
+        editor.refresh();
+      });
+
+      $(document).on("addFieldToSource", function(e, field){
+        if ($(element).data("template")){
+          editor.replaceSelection("{{" + field.name() + "}}");
         }
-        else {
-          $(".chartComponent").addClass("alert").text("${_('The graphical facets works just with numbers or dates. Please choose another field.')}")
+      });
+
+      $(document).on("addFunctionToSource", function(e, fn){
+        if ($(element).data("template")){
+          editor.replaceSelection(fn);
         }
-      }
-      else {
-        $(".chartComponent").addClass("alert").text("${_('There was an error initializing the graphical facet component.')}")
-      }
+      });
+
+      $(".chosen-select").chosen({
+        disable_search_threshold: 10,
+        width: "75%"
+      });
+      $('.chosen-select').trigger('chosen:updated');
+
+      var sourceDelay = -1;
+      editor.on("change", function (cm) {
+        clearTimeout(sourceDelay);
+        var _cm = cm;
+        sourceDelay = setTimeout(function () {
+          var _enc = $("<span>").html(_cm.getValue());
+          if (_enc.find("style").length > 0){
+            var parser = new less.Parser();
+            $(_enc.find("style")).each(function(cnt, item){
+              var _less = "#result-container {" + $(item).text() + "}";
+              try {
+                parser.parse(_less, function (err, tree) {
+                  $(item).text(tree.toCSS());
+                });
+              }
+              catch (e){}
+            });
+            valueAccessor().data(_enc.html());
+          }
+          else {
+            valueAccessor().data(_cm.getValue());
+          }
+          if ($(".widget-html-pill").parent().hasClass("active")){
+            $("[contenteditable=true]").html(stripHtmlFromFunctions(valueAccessor().data()));
+          }
+        }, 100);
+      });
+
+      ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
+        wrapperElement.remove();
+      });
+    },
+    update: function (element, valueAccessor, allBindingsAccessor) {
+      var editor = element.editor;
+      editor.refresh();
     }
-    else {
-      $(".chartComponent").hide();
+  };
+
+
+  viewModel = new SearchViewModel(${ collection.get_c(user) | n,unicode }, ${ query | n,unicode }, ${ initial | n,unicode });
+  ko.applyBindings(viewModel);
+
+  viewModel.init(function(data){
+    $(".chosen-select").trigger("chosen:updated");
+  });
+  viewModel.isRetrievingResults.subscribe(function(value){
+    if (!value){
+      resizeFieldsList();
     }
+  });
 
+  $("#addFacetDemiModal").on("hidden", function () {
+    if (typeof selectedWidget.hasBeenSelected == "undefined"){
+      addFacetDemiModalFieldCancel();
+    }
   });
+
+});
+
+  function toggleGridFieldsSelection() {
+    if (viewModel.collection.template.fields().length > 0) {
+      viewModel.collection.template.fieldsSelected([])
+    }
+    else {
+      var _fields = [];
+      $.each(viewModel.collection.fields(), function (index, field) {
+        _fields.push(field.name());
+      });
+      viewModel.collection.template.fieldsSelected(_fields);
+    }
+  }
+
+  var selectedWidget = null;
+  function showAddFacetDemiModal(widget) {
+    if (["resultset-widget", "html-resultset-widget", "filter-widget"].indexOf(widget.widgetType()) == -1) {      
+      viewModel.collection.template.fieldsModalFilter("");
+      viewModel.collection.template.fieldsModalType(widget.widgetType());
+      viewModel.collection.template.fieldsModalFilter.valueHasMutated();
+      $('#addFacetInput').typeahead({
+          'source': viewModel.collection.template.availableWidgetFieldsNames(), 
+          'updater': function(item) {
+              addFacetDemiModalFieldPreview({'name': function(){return item}});
+              return item;
+           }
+      });
+      selectedWidget = widget;
+      $("#addFacetDemiModal").modal("show");
+      $("#addFacetDemiModal input[type='text']").focus();
+    }
+  }
+
+
+  function addFacetDemiModalFieldPreview(field) {
+    var _existingFacet = viewModel.collection.getFacetById(selectedWidget.id());
+    if (selectedWidget != null) {
+      selectedWidget.hasBeenSelected = true;
+      selectedWidget.isLoading(true);
+      viewModel.collection.addFacet({'name': field.name(), 'widget_id': selectedWidget.id(), 'widgetType': selectedWidget.widgetType()});
+      if (_existingFacet != null) {
+        _existingFacet.label(field.name());
+        _existingFacet.field(field.name());
+      }
+      $("#addFacetDemiModal").modal("hide");
+    }
+  }
+  
+  function addFacetDemiModalFieldCancel() {
+    viewModel.removeWidget(selectedWidget);
+  }
+
 </script>
 
 ${ commonfooter(messages) | n,unicode }

+ 0 - 1853
apps/search/src/search/templates/search2.mako

@@ -1,1853 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%!
-from desktop.views import commonheader, commonfooter
-from django.utils.translation import ugettext as _
-%>
-
-${ commonheader(_('Search'), "search", user, "80px") | n,unicode }
-
-<script type="text/javascript">
-  if (window.location.hash != ""){
-    location.href = "/search/?" + window.location.hash.substr(1);
-  }
-</script>
-
-<div class="search-bar">
-  % if user.is_superuser:
-    <div class="pull-right" style="padding-right:50px">
-      <button type="button" title="${ _('Edit') }" rel="tooltip" data-placement="bottom" data-bind="click: toggleEditing, css: {'btn': true, 'btn-inverse': isEditing}"><i class="fa fa-pencil"></i></button>
-      <button type="button" title="${ _('Save') }" rel="tooltip" data-placement="bottom" data-loading-text="${ _("Saving...") }" data-bind="click: save, css: {'btn': true}"><i class="fa fa-save"></i></button>
-      <button type="button" title="${ _('Save') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}"><i class="fa fa-cog"></i></button>
-      ## for enable, live search, max number of downloads, change solr
-      <button type="button" title="${ _('Share') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}"><i class="fa fa-link"></i></button>
-      &nbsp;&nbsp;&nbsp;            
-      <a class="btn" href="${ url('search:new_search') }" title="${ _('New') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}"><i class="fa fa-file-o"></i></a>
-      <a class="btn" href="${ url('search:admin_collections') }" title="${ _('Collections') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}"><i class="fa fa-tags"></i></a> 
-    </div>
-  % endif
-  
-  <form data-bind="visible: columns().length == 0">  
-    ${ _('Search') }
-    <!-- ko if: $root.initial.collections -->
-    <select data-bind="options: $root.initial.collections, value: $root.collection.name">
-    </select>
-    <!-- /ko -->
-  </form>
-  
-  <form class="form-search" style="margin: 0" data-bind="submit: searchBtn, visible: columns().length != 0"">
-    <strong>${_("Search")}</strong>
-    <div class="input-append">
-      <div class="selectMask">
-        <span
-            data-bind="editable: collection.label, editableOptions: {enabled: $root.isEditing(), placement: 'right'}">
-        </span>
-        ##<i class="fa fa-edit" data-bind="visible: $root.isEditing() && ! $root.changeCollection(), click: function(){$root.changeCollection(true);}"></i>
-        <!-- ko if: $root.isEditing() && $root.changeCollection() -->
-        <select data-bind="options: $root.initial.collections, value: $root.collection.name">
-        </select>        
-        <!-- /ko -->
-      </div>
-
-      <span data-bind="foreach: query.qs">
-        <input data-bind="value: q" maxlength="256" type="text" class="search-query input-xlarge" style="cursor: auto;">
-        <!-- ko if: $index() >= 1 -->
-        <a class="btn" href="javascript:void(0)" data-bind="click: $root.query.removeQ"><i class="fa fa-minus"></i></a>
-        <!-- /ko -->
-      </span>
-
-      <a class="btn" href="javascript:void(0)" data-bind="click: $root.query.addQ"><i class="fa fa-plus"></i></a>
-
-      <button type="submit" id="search-btn" class="btn btn-inverse" style="margin-left:10px"><i class="fa fa-search"></i></button>
-    </div>
-  </form>
-</div>
-
-<div class="card card-toolbar" data-bind="slideVisible: isEditing">
-  <div style="float: left">
-    <div class="toolbar-label">${_('LAYOUT')}</div>
-    <a href="javascript: oneThirdLeftLayout()" onmouseover="viewModel.previewColumns('oneThirdLeft')" onmouseout="viewModel.previewColumns('')">
-      <div class="layout-container">
-        <div class="layout-box" style="width: 24px"></div>
-        <div class="layout-box" style="width: 72px; margin-left: 4px"></div>
-      </div>
-    </a>
-    <a href="javascript: fullLayout()" onmouseover="viewModel.previewColumns('full')" onmouseout="viewModel.previewColumns('')">
-      <div class="layout-container">
-        <div class="layout-box" style="width: 100px;"></div>
-      </div>
-    </a>
-    <a data-bind="visible: columns().length == 0" href="javascript: magicLayout(viewModel)" onmouseover="viewModel.previewColumns('magic')" onmouseout="viewModel.previewColumns('')">
-      <div class="layout-container">
-        <div class="layout-box" style="width: 100px;"><i class="fa fa-magic"></i></div>
-      </div>
-    </a>
-  </div>
-
-  <div style="float: left; margin-left: 20px" data-bind="visible: columns().length > 0">
-    <div class="toolbar-label">${_('WIDGETS')}</div>
-    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableResultset() },
-                    draggable: {data: draggableResultset(), isEnabled: availableDraggableResultset,
-                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
-                              'stop': function(event, ui){$('.card-body').slideDown('fast'); $root.collection.template.isGridLayout(true); }}}"
-         title="${_('Grid Results')}" rel="tooltip" data-placement="top">
-         <a data-bind="style: { cursor: $root.availableDraggableResultset() ? 'move' : 'default' }">
-                       <i class="fa fa-table"></i>
-         </a>
-    </div>
-    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableResultset() },
-                    draggable: {data: draggableHtmlResultset(), 
-                    isEnabled: availableDraggableResultset, 
-                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
-                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)}); $root.collection.template.isGridLayout(false); }}}"
-         title="${_('HTML Results')}" rel="tooltip" data-placement="top">
-         <a data-bind="style: { cursor: $root.availableDraggableResultset() ? 'move' : 'default' }">
-                       <i class="fa fa-code"></i>
-         </a>
-    </div>
-    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableChart() },
-                    draggable: {data: draggableFacet(), isEnabled: availableDraggableChart, 
-                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
-                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
-         title="${_('Text Facet')}" rel="tooltip" data-placement="top">
-         <a data-bind="style: { cursor: $root.availableDraggableChart() ? 'move' : 'default' }">
-                       <i class="fa fa-sort-amount-asc"></i>
-         </a>
-    </div>
-    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableChart() },
-                    draggable: {data: draggablePie(), isEnabled: availableDraggableChart, 
-                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
-                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
-         title="${_('Pie Chart')}" rel="tooltip" data-placement="top">
-         <a data-bind="style: { cursor: $root.availableDraggableChart() ? 'move' : 'default' }">
-                       <i class="hcha hcha-pie-chart"></i>
-         </a>
-    </div>
-    <!-- <div class="draggable-widget" data-bind="draggable: {data: draggableHit(), options: {'start': function(event, ui){$('.card-body').slideUp('fast');}, 'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}" title="${_('Hit Count')}" rel="tooltip" data-placement="top"><a data-bind="attr: {href: $root.availableDraggableResultset()}, css: {'btn-inverse': ! $root.availableDraggableResultset() }, style: { cursor: $root.availableDraggableResultset() ? 'move' : 'default' }"><i class="fa fa-tachometer"></i></a></div> -->
-    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableChart() },
-                    draggable: {data: draggableBar(), isEnabled: availableDraggableChart, 
-                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
-                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
-         title="${_('Bar Chart')}" rel="tooltip" data-placement="top">
-         <a data-bind="style: { cursor: $root.availableDraggableChart() ? 'move' : 'default' }">
-                       <i class="hcha hcha-bar-chart"></i>
-         </a>
-    </div>
-    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableNumbers() },
-                    draggable: {data: draggableLine(), isEnabled: availableDraggableNumbers, 
-                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
-                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
-         title="${_('Line')}" rel="tooltip" data-placement="top">
-         <a data-bind="style: { cursor: $root.availableDraggableNumbers() ? 'move' : 'default' }">
-                       <i class="hcha hcha-line-chart"></i>
-         </a>
-    </div>
-    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableHistogram() },
-                    draggable: {data: draggableHistogram(), isEnabled: availableDraggableHistogram, 
-                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
-                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
-         title="${_('Histogram')}" rel="tooltip" data-placement="top">
-         <a data-bind="style: { cursor: $root.availableDraggableHistogram() ? 'move' : 'default' }">
-                       <i class="hcha hcha-timeline-chart"></i>
-         </a>
-    </div>
-    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableFilter() },
-                    draggable: {data: draggableFilter(), isEnabled: availableDraggableFilter, 
-                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
-                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
-         title="${_('Filter Bar')}" rel="tooltip" data-placement="top">
-         <a data-bind="style: { cursor: $root.availableDraggableFilter() ? 'move' : 'default' }">
-                       <i class="fa fa-filter"></i>
-         </a>
-    </div>
-    <div data-bind="css: { 'draggable-widget': true, 'disabled': !availableDraggableChart() },
-                    draggable: {data: draggableMap(), isEnabled: availableDraggableChart, 
-                    options: {'start': function(event, ui){lastWindowScrollPosition = $(window).scrollTop();$('.card-body').slideUp('fast');},
-                              'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}}"
-         title="${_('Map')}" rel="tooltip" data-placement="top">
-         <a data-bind="style: { cursor: $root.availableDraggableChart() ? 'move' : 'default' }">
-                       <i class="hcha hcha-map-chart"></i>
-         </a>
-   </div>
-  </div>
-  <div class="clearfix"></div>
-</div>
-
-<div id="emptyDashboard" data-bind="visible: !isEditing() && columns().length == 0">
-  <div style="float:left; padding-top: 90px; margin-right: 20px; text-align: center; width: 260px">${_('Click on the pencil to get started with your dashboard!')}</div>
-  <img src="/search/static/art/hint_arrow.png" />
-</div>
-
-
-<div data-bind="visible: isEditing() && previewColumns() != '' && columns().length == 0, css:{'with-top-margin': isEditing()}">
-  <div class="container-fluid">
-    <div class="row-fluid" data-bind="visible: previewColumns() == 'oneThirdLeft'">
-      <div class="span3 preview-row"></div>
-      <div class="span9 preview-row"></div>
-    </div>
-    <div class="row-fluid" data-bind="visible: previewColumns() == 'full'">
-      <div class="span12 preview-row">
-      </div>
-    </div>
-    <div class="row-fluid" data-bind="visible: previewColumns() == 'magic'">
-      <div class="span12 preview-row">
-        ${ _('Template predefined with some widgets.') }
-      </div>
-    </div>
-  </div>
-</div>
-
-<div data-bind="css: {'dashboard': true, 'with-top-margin': isEditing()}">
-  <div class="container-fluid">
-    <div class="row-fluid" data-bind="template: { name: 'column-template', foreach: columns}">
-    </div>
-    <div class="clearfix"></div>
-  </div>
-</div>
-
-<script type="text/html" id="column-template">
-  <div data-bind="css: klass">
-    <div class="container-fluid" data-bind="visible: $root.isEditing">
-      <div data-bind="css: {'add-row': true, 'is-editing': $root.isEditing}, sortable: { data: drops, isEnabled: $root.isEditing, options: {'placeholder': 'add-row-highlight', 'greedy': true, 'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}, dragged: function(widget){var _r = $data.addEmptyRow(true); _r.addWidget(widget);$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});showAddFacetDemiModal(widget);viewModel.search()}}"></div>
-    </div>
-    <div data-bind="template: { name: 'row-template', foreach: rows}">
-    </div>
-    <div class="container-fluid" data-bind="visible: $root.isEditing">
-      <div data-bind="css: {'add-row': true, 'is-editing': $root.isEditing}, sortable: { data: drops, isEnabled: $root.isEditing, options: {'placeholder': 'add-row-highlight', 'greedy': true, 'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}}, dragged: function(widget){var _r = $data.addEmptyRow(); _r.addWidget(widget);$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});showAddFacetDemiModal(widget);viewModel.search()}}"></div>
-    </div>
-  </div>
-</script>
-
-<script type="text/html" id="row-template">
-  <div class="emptyRow" data-bind="visible: widgets().length == 0 && $index() == 0 && $root.isEditing() && $parent.size() > 4 && $parent.rows().length == 1">
-    <img src="/search/static/art/hint_arrow_flipped.png" style="float:left; margin-right: 10px"/>
-    <div style="float:left; text-align: center; width: 260px">${_('Drag any of the widgets inside your empty row')}</div>
-    <div class="clearfix"></div>
-  </div>
-  <div class="container-fluid">
-    <div class="row-header" data-bind="visible: $root.isEditing">
-      <span class="muted">${_('Row')}</span>
-      <div style="display: inline; margin-left: 60px">
-        <a href="javascript:void(0)" data-bind="visible: $index()<$parent.rows().length-1, click: function(){moveDown($parent, this)}"><i class="fa fa-chevron-down"></i></a>
-        <a href="javascript:void(0)" data-bind="visible: $index()>0, click: function(){moveUp($parent, this)}"><i class="fa fa-chevron-up"></i></a>
-        <a href="javascript:void(0)" data-bind="visible: $parent.rows().length > 1, click: function(){remove($parent, this)}"><i class="fa fa-times"></i></a>
-      </div>
-    </div>
-    <div data-bind="css: {'row-fluid': true, 'row-container':true, 'is-editing': $root.isEditing},
-        sortable: { template: 'widget-template', data: widgets, isEnabled: $root.isEditing, 
-        options: {'handle': '.move-widget', 'opacity': 0.7, 'placeholder': 'row-highlight', 'greedy': true, 
-            'stop': function(event, ui){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});}, 
-            'helper': function(event){lastWindowScrollPosition = $(window).scrollTop(); $('.card-body').slideUp('fast'); var _par = $('<div>');_par.addClass('card card-widget');var _title = $('<h2>');_title.addClass('card-heading simple');_title.text($(event.toElement).text());_title.appendTo(_par);_par.height(80);_par.width(180);return _par;}},
-            dragged: function(widget){$('.card-body').slideDown('fast', function(){$(window).scrollTop(lastWindowScrollPosition)});showAddFacetDemiModal(widget);viewModel.search()}}">
-    </div>
-  </div>
-</script>
-
-<script type="text/html" id="widget-template">
-  <div data-bind="attr: {'id': 'wdg_'+ id(),}, css: klass">
-    <h2 class="card-heading simple">
-      <span data-bind="visible: $root.isEditing">
-        <a href="javascript:void(0)" class="move-widget"><i class="fa fa-arrows"></i></a>
-        <a href="javascript:void(0)" data-bind="click: compress, visible: size() > 1"><i class="fa fa-step-backward"></i></a>
-        <a href="javascript:void(0)" data-bind="click: expand, visible: size() < 12"><i class="fa fa-step-forward"></i></a>
-        &nbsp;
-      </span>
-      <span data-bind="with: $root.collection.getFacetById(id())">
-        <span data-bind="editable: label, editableOptions: {enabled: $root.isEditing()}"></span>
-      </span>
-      <!-- ko ifnot: $root.collection.getFacetById(id()) -->
-        <span data-bind="editable: name, editableOptions: {enabled: $root.isEditing()}"></span>
-      <!-- /ko -->
-      <div class="inline pull-right" data-bind="visible: $root.isEditing">
-        <a href="javascript:void(0)" data-bind="click: function(){remove($parent, this)}"><i class="fa fa-times"></i></a>
-      </div>
-    </h2>
-    <div class="card-body" style="padding: 5px;">    
-      <div data-bind="template: { name: function() { return widgetType(); } }" class="widget-main-section"></div>
-    </div>
-  </div>
-</script>
-
-<script type="text/html" id="empty-widget">
-  ${ _('This is an empty widget.')}
-</script>
-
-
-<script type="text/html" id="hit-widget">
-  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
-
-  <!-- /ko -->
-
-  <!-- ko if: $root.getFacetFromQuery(id()) -->
-  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
-    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">      
-      ${ _('Label') }: <input type="text" data-bind="value: label" />
-    </div>  
-
-    <span data-bind="text: query" />: <span data-bind="text: count" />
-  </div>
-  <!-- /ko -->
-</script>
-
-<script type="text/html" id="facet-toggle">
-    <!-- ko if: type() == 'range' -->
-      ${ _('Start') }:
-      <input type="text" class="input-large" data-bind="value: properties.start" />
-      <br/>
-      ${ _('End') }: <input type="text" class="input-large" data-bind="value: properties.end" />
-      <br/>
-      ${ _('Gap') }: <input type="text" class="input-small" data-bind="value: properties.gap" />
-      <br/>
-      ${ _('Min') }:
-      <input type="text" class="input-medium" data-bind="value: properties.min" />
-      <br/>
-      ${ _('Max') }: <input type="text" class="input-medium" data-bind="value: properties.max" />
-      <br/>      
-    <!-- /ko -->
-    <!-- ko if: type() == 'field' -->
-      ${ _('Limit') }: <input type="text" class="input-medium" data-bind="value: properties.limit" />
-    <!-- /ko -->
-
-    <a href="javascript: void(0)" class="btn btn-loading" data-bind="visible: properties.canRange, click: $root.collection.toggleRangeFacet" data-loading-text="...">
-      <i class="fa" data-bind="css: { 'fa-arrows-h': type() == 'range', 'fa-circle': type() == 'field' }, attr: { title: type() == 'range' ? 'Range' : 'Term' }"></i>
-    </a>
-    <a href="javascript: void(0)" class="btn btn-loading" data-bind="click: $root.collection.toggleSortFacet" data-loading-text="...">          
-      <i class="fa" data-bind="css: { 'fa-caret-down': properties.sort() == 'desc', 'fa-caret-up': properties.sort() == 'asc' }"></i>
-    </a>
-</script>
-
-<script type="text/html" id="facet-widget">
-  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
-  <!-- /ko -->
-
-  <div class="widget-spinner" data-bind="visible: isLoading()">
-    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-  </div>
-
-  <!-- ko if: $root.getFacetFromQuery(id()) -->
-  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
-    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">
-      <span data-bind="template: { name: 'facet-toggle', afterRender: function(){ $root.getWidgetById($parent.id).isLoading(false); } }">
-      </span>
-    </div>
-    <div data-bind="with: $root.collection.getFacetById($parent.id())">
-	    <!-- ko if: type() != 'range' -->
-        <div data-bind="foreach: $parent.counts">
-          <div>
-            <a href="javascript: void(0)">              
-              <!-- ko if: $index() != $parent.properties.limit() -->
-                <!-- ko if: ! $data.selected -->
-                  <span data-bind="text: $data.value, click: function(){ $root.query.toggleFacet({facet: $data, widget_id: $parent.id()}) }"></span>
-                  <span class="counter" data-bind="text: ' (' + $data.count + ')', click: function(){ $root.query.toggleFacet({facet: $data, widget_id: $parent.id()}) }"></span>                
-                <!-- /ko -->
-                <!-- ko if: $data.selected -->
-                  <span data-bind="click: function(){ $root.query.toggleFacet({facet: $data, widget_id: $parent.id()}) }">
-                    <span data-bind="text: $data.value"></span>
-                    <i class="fa fa-times"></i>
-                  </span>
-                <!-- /ko -->
-              <!-- /ko -->
-              <!-- ko if: $index() == $parent.properties.limit() -->
-                <!-- ko if: $parent.properties.prevLimit == undefined || $parent.properties.prevLimit == $parent.properties.limit() -->
-                  <span data-bind="click: function(){ $root.collection.upDownFacetLimit($parent.id(), 'up') }">
-                    ${ _('Show more...') }
-                  </span>
-                <!-- /ko -->
-                <!-- ko if: $parent.properties.prevLimit != undefined && $parent.properties.prevLimit != $parent.properties.limit() -->
-                  <span data-bind="click: function(){ $root.collection.upDownFacetLimit($parent.id(), 'up') }">
-                    ${ _('Show more') }
-                  </span> 
-                  /             
-                  <span data-bind="click: function(){ $root.collection.upDownFacetLimit($parent.id(), 'down') }">
-                    ${ _('less...') }
-                  </span>                    
-                </span>
-                <!-- /ko -->
-              <!-- /ko -->
-            </a>
-          </div>
-        </div>
-	    <!-- /ko -->
-	    <!-- ko if: type() == 'range' -->
-        <div data-bind="foreach: $parent.counts">
-          <div>
-            <a href="javascript: void(0)">
-              <!-- ko if: ! selected --> 
-                <span data-bind="click: function(){ $root.query.selectRangeFacet({count: $data.value, widget_id: $parent.id(), from: $data.from, to: $data.to, cat: $data.field}) }">
-                  <span data-bind="text: $data.from + ' - ' + $data.to"></span>
-                  <span class="counter" data-bind="text: ' (' + $data.value + ')'"></span>
-                </span>
-              <!-- /ko -->
-              <!-- ko if: selected -->
-                <span data-bind="click: function(){ $root.query.selectRangeFacet({count: $data.value, widget_id: $parent.id(), from: $data.from, to: $data.to, cat: $data.field}) }">
-                  <span data-bind="text: $data.from + ' - ' + $data.to"></span>
-                  <i class="fa fa-times"></i>
-                </span>
-              <!-- /ko -->
-            </a>
-          </div>
-        </div>
-	    <!-- /ko -->    
-    </div>
-  </div>
-  <!-- /ko -->
-</script>
-
-<script type="text/html" id="resultset-widget">
-  <!-- ko if: $root.collection.template.isGridLayout() -->
-    <div style="float:left; margin-right: 10px" >
-      <div data-bind="visible: ! $root.collection.template.showFieldList()" style="padding-top: 5px; display: inline-block">
-        <a href="javascript: void(0)"  data-bind="click: function(){ $root.collection.template.showFieldList(true) }">
-          <i class="fa fa-chevron-right"></i>
-        </a>
-      </div>
-    </div>
-    <div data-bind="visible: $root.collection.template.showFieldList()" style="float:left; margin-right: 10px; background-color: #F6F6F6; padding: 5px">
-      <span data-bind="visible: $root.collection.template.showFieldList()">
-        <div>
-          <a href="javascript: void(0)" class="pull-right" data-bind="click: function(){ $root.collection.template.showFieldList(false) }">
-            <i class="fa fa-chevron-left"></i>
-          </a>
-          <input type="text" data-bind="value: $root.collection.template.fieldsAttributesFilter, valueUpdate:'afterkeydown'" placeholder="${_('Filter fields')}" style="width: 70%; margin-bottom: 10px" />
-        </div>
-        <div style="border-bottom: 1px solid #CCC; padding-bottom: 4px">
-          <a href="javascript: void(0)" class="btn btn-mini"
-            data-bind="click: toggleGridFieldsSelection, css: { 'btn-inverse': $root.collection.template.fields().length > 0 }"
-            style="margin-right: 2px;">
-            <i class="fa fa-square-o"></i>
-          </a>
-          <strong>${_('Field Name')}</strong>
-        </div>
-        <div class="fields-list" data-bind="foreach: $root.collection.template.filteredAttributeFields" style="max-height: 230px; overflow-y: auto; padding-left: 4px">
-          <label class="checkbox">
-            <input type="checkbox" data-bind="checkedValue: name, checked: $root.collection.template.fieldsSelected" />
-            <span data-bind="text: name"></span>
-          </label>
-        </div>
-      </span>
-    </div>
-
-    <div>
-      <div data-bind="visible: !$root.isRetrievingResults() && $root.results().length == 0">
-        ${ _('Your search did not match any documents.') }
-      </div>
-    
-      <!-- ko if: $root.response().response -->
-        <div data-bind="template: {name: 'resultset-pagination', data: $root.response() }"></div>
-      <!-- /ko -->
-      <div style="overflow-x: auto">
-        <table id="result-container" data-bind="visible: !$root.isRetrievingResults()" style="margin-top: 0; width: 100%">
-          <thead>
-            <tr data-bind="visible: $root.results().length > 0">
-              <th style="width: 18px">&nbsp;</th>
-              <!-- ko foreach: $root.collection.template.fieldsSelected -->
-              <th data-bind="with: $root.collection.getTemplateField($data), event: { mouseover: $root.enableGridlayoutResultChevron, mouseout: $root.disableGridlayoutResultChevron }" style="white-space: nowrap">
-                <div style="display: inline-block; width:20px;">
-                <a href="javascript: void(0)" data-bind="click: function(){ $root.collection.translateSelectedField($index(), 'left'); }">
-                    <i class="fa fa-chevron-left" data-bind="visible: $root.toggledGridlayoutResultChevron() && $index() > 0"></i>
-                    <i class="fa fa-chevron-left" style="color: #FFF" data-bind="visible: !$root.toggledGridlayoutResultChevron() || $index() == 0"></i>
-                </a>
-                </div>
-                <div style="display: inline-block;">
-                <a href="javascript: void(0)" title="${ _('Click to sort') }">
-                  <span data-bind="text: name, click: $root.collection.toggleSortColumnGridLayout"></span>
-                  <i class="fa" data-bind="visible: sort.direction() != null, css: { 'fa-chevron-down': sort.direction() == 'desc', 'fa-chevron-up': sort.direction() == 'asc' }"></i>
-                </a>
-                  </div>
-                <div style="display: inline-block; width:20px;">
-                <a href="javascript: void(0)" data-bind="click: function(){ $root.collection.translateSelectedField($index(), 'right'); }">
-                    <i class="fa fa-chevron-right" data-bind="visible: $root.toggledGridlayoutResultChevron() && $index() < $root.collection.template.fields().length - 1"></i>
-                  <i class="fa fa-chevron-up" style="color: #FFF" data-bind="visible: !$root.toggledGridlayoutResultChevron() || $index() == $root.collection.template.fields().length - 1,"></i>
-                </a>
-                </div>
-              </th>
-              <!-- /ko -->
-            </tr>
-            <tr data-bind="visible: $root.collection.template.fieldsSelected().length == 0">
-              <th style="width: 18px">&nbsp;</th>
-              <th>${ ('Document') }</th>
-            </tr>
-          </thead>
-          <tbody data-bind="foreach: { data: $root.results, as: 'documents' }" class="result-tbody">
-            <tr class="result-row" data-bind="attr: {'id': 'doc_' + $data['id']}">
-              <td><a href="javascript:void(0)" data-bind="click: toggleDocDetails"><i class="fa fa-caret-right"></i></a></td>
-              <!-- ko foreach: $data['row'] -->
-                <td data-bind="html: $data"></td>
-              <!-- /ko -->
-            </tr>
-          </tbody>
-        </table>
-      </div>
-      <div class="widget-spinner" data-bind="visible: $root.isRetrievingResults()">
-        <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-        <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-      </div>	  
-    </div>
-  <!-- /ko -->
-</script>
-
-<script type="text/html" id="html-resultset-widget">
-  <!-- ko ifnot: $root.collection.template.isGridLayout() -->
-    <div data-bind="visible: $root.isEditing" style="margin-bottom: 20px">
-      <ul class="nav nav-pills">
-        <li class="active"><a href="javascript: void(0)" class="widget-editor-pill">${_('Editor')}</a></li>
-        <li><a href="javascript: void(0)" class="widget-html-pill">${_('HTML')}</a></li>
-        <li><a href="javascript: void(0)" class="widget-css-pill">${_('CSS & JS')}</a></li>
-        <li><a href="javascript: void(0)" class="widget-settings-pill">${_('Properties')}</a></li>
-      </ul>
-    </div>
-
-    <!-- ko if: $root.isEditing() -->
-      <div class="widget-section widget-editor-section">
-        <div class="row-fluid">
-          <div class="span9">
-            <div data-bind="freshereditor: {data: $root.collection.template.template}"></div>
-          </div>
-          <div class="span3">
-            <h5 class="editor-title">${_('Available Fields')}</h5>
-            <select data-bind="options: $root.collection.fields, optionsText: 'name', value: $root.collection.template.selectedVisualField" class="input-large chosen-select"></select>
-            <button title="${ _('Click on this button to add the field') }" class="btn plus-btn" data-bind="click: $root.collection.template.addFieldToVisual">
-              <i class="fa fa-plus"></i>
-            </button>
-
-            <h5 class="editor-title" style="margin-top: 30px">${_('Available Functions')}</h2>
-            <select id="visualFunctions" data-bind="value: $root.collection.template.selectedVisualFunction" class="input-large chosen-select">
-              <option title="${ _('Formats date or timestamp in DD-MM-YYYY') }" value="{{#date}} {{/date}}">{{#date}}</option>
-              <option title="${ _('Formats date or timestamp in HH:mm:ss') }" value="{{#time}} {{/time}}">{{#time}}</option>
-              <option title="${ _('Formats date or timestamp in DD-MM-YYYY HH:mm:ss') }" value="{{#datetime}} {{/datetime}}">{{#datetime}}</option>
-              <option title="${ _('Formats a date in the full format') }" value="{{#fulldate}} {{/fulldate}}">{{#fulldate}}</option>
-              <option title="${ _('Formats a date as a Unix timestamp') }" value="{{#timestamp}} {{/timestamp}}">{{#timestamp}}</option>
-              <option title="${ _('Formats a Unix timestamp as Ns, Nmin, Ndays... ago') }" value="{{#fromnow}} {{/fromnow}}">{{#fromnow}}</option>
-              <option title="${ _('Downloads and embed the file in the browser') }" value="{{#embeddeddownload}} {{/embeddeddownload}}">{{#embeddeddownload}}</option>
-              <option title="${ _('Downloads the linked file') }" value="{{#download}} {{/download}}">{{#download}}</option>
-              <option title="${ _('Preview file in File Browser') }" value="{{#preview}} {{/preview}}">{{#preview}}</option>
-              <option title="${ _('Truncate a value after 100 characters') }" value="{{#truncate100}} {{/truncate100}}">{{#truncate100}}</option>
-              <option title="${ _('Truncate a value after 250 characters') }" value="{{#truncate250}} {{/truncate250}}">{{#truncate250}}</option>
-              <option title="${ _('Truncate a value after 500 characters') }" value="{{#truncate500}} {{/truncate500}}">{{#truncate500}}</option>
-            </select>
-            <button title="${ _('Click on this button to add the function') }" class="btn plus-btn" data-bind="click: $root.collection.template.addFunctionToVisual">
-              <i class="fa fa-plus"></i>
-            </button>
-            <p class="muted" style="margin-top: 10px"></p>
-          </div>
-        </div>
-      </div>
-      <div class="widget-section widget-html-section" style="display: none">
-        <div class="row-fluid">
-          <div class="span9">
-            <textarea data-bind="codemirror: {data: $root.collection.template.template, lineNumbers: true, htmlMode: true, mode: 'text/html' }" data-template="true"></textarea>
-          </div>
-          <div class="span3">
-            <h5 class="editor-title">${_('Available Fields')}</h2>
-            <select data-bind="options: $root.collection.fields, optionsText: 'name', value: $root.collection.template.selectedSourceField" class="input-medium chosen-select"></select>
-            <button title="${ _('Click on this button to add the field') }" class="btn plus-btn" data-bind="click: $root.collection.template.addFieldToSource">
-              <i class="fa fa-plus"></i>
-            </button>
-
-            <h5 class="editor-title" style="margin-top: 30px">${_('Available Functions')}</h2>
-            <select id="sourceFunctions" data-bind="value: $root.collection.template.selectedSourceFunction" class="input-medium chosen-select">
-              <option title="${ _('Formats a date in the DD-MM-YYYY format') }" value="{{#date}} {{/date}}">{{#date}}</option>
-              <option title="${ _('Formats a date in the HH:mm:ss format') }" value="{{#time}} {{/time}}">{{#time}}</option>
-              <option title="${ _('Formats a date in the DD-MM-YYYY HH:mm:ss format') }" value="{{#datetime}} {{/datetime}}">{{#datetime}}</option>
-              <option title="${ _('Formats a date in the full format') }" value="{{#fulldate}} {{/fulldate}}">{{#fulldate}}</option>
-              <option title="${ _('Formats a date as a Unix timestamp') }" value="{{#timestamp}} {{/timestamp}}">{{#timestamp}}</option>
-              <option title="${ _('Shows the relative time') }" value="{{#fromnow}} {{/fromnow}}">{{#fromnow}}</option>
-              <option title="${ _('Downloads and embed the file in the browser') }" value="{{#embeddeddownload}} {{/embeddeddownload}}">{{#embeddeddownload}}</option>
-              <option title="${ _('Downloads the linked file') }" value="{{#download}} {{/download}}">{{#download}}</option>
-              <option title="${ _('Preview file in File Browser') }" value="{{#preview}} {{/preview}}">{{#preview}}</option>
-              <option title="${ _('Truncate a value after 100 characters') }" value="{{#truncate100}} {{/truncate100}}">{{#truncate100}}</option>
-              <option title="${ _('Truncate a value after 250 characters') }" value="{{#truncate250}} {{/truncate250}}">{{#truncate250}}</option>
-              <option title="${ _('Truncate a value after 500 characters') }" value="{{#truncate500}} {{/truncate500}}">{{#truncate500}}</option>
-            </select>
-            <button title="${ _('Click on this button to add the function') }" class="btn plus-btn" data-bind="click: $root.collection.template.addFunctionToSource">
-              <i class="fa fa-plus"></i>
-            </button>
-            <p class="muted" style="margin-top: 10px"></p>
-          </div>
-        </div>
-      </div>
-      <div class="widget-section widget-css-section" style="display: none">
-        <textarea data-bind="codemirror: {data: $root.collection.template.extracode, lineNumbers: true, htmlMode: true, mode: 'text/html' }"></textarea>
-      </div>
-      <div class="widget-section widget-settings-section" style="display: none, min-height:200px">
-        ${ _('Sorting') }
-        
-        <div data-bind="foreach: $root.collection.template.fieldsSelected">
-          <span data-bind="text: $data"></span>
-        </div>
-        <br/>  
-      </div>
-    <!-- /ko -->
-
-    <div style="overflow-x: auto">
-      <div data-bind="visible: $root.results().length == 0">
-        ${ _('Your search did not match any documents.') }
-      </div>
-    
-      <!-- ko if: $root.response().response -->
-        <div data-bind="template: {name: 'resultset-pagination', data: $root.response() }"></div>
-      <!-- /ko -->
-    
-      <div id="result-container" data-bind="foreach: $root.results">
-        <div class="result-row" data-bind="html: $data"></div>
-      </div>    
-    
-      <div class="widget-spinner" data-bind="visible: $root.isRetrievingResults()">
-        <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-        <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-      </div>
-    </div>
-  <!-- /ko -->
-</script>
-
-<script type="text/html" id="resultset-pagination">
-<div style="text-align: center; margin-top: 4px">
-  <a href="javascript: void(0)" title="${ _('Previous') }">
-    <span data-bind="text: name, click: $root.collection.toggleSortColumnGridLayout"></span>
-    <i class="fa fa-arrow-left" data-bind="
-        visible: $data.response.start * 1.0 >= $root.collection.template.rows() * 1.0,
-        click: function() { $root.query.paginate('prev') }">
-    </i></a>
-
-  ${ _('Showing') }
-  <span data-bind="text: ($data.response.start + 1)"></span>
-  ${ _('to') }
-  <span data-bind="text: ($data.response.start + $root.collection.template.rows())"></span>
-  ${ _('of') }
-  <span data-bind="text: $data.response.numFound"></span>
-  ${ _(' results.') }
-
-  ${ _('Show') }
-  <span data-bind="visible: $root.isEditing()" class="spinedit-pagination">
-    <input type="text" data-bind="spinedit: $root.collection.template.rows, valueUpdate:'afterkeydown'" style="text-align: center; margin-bottom: 0" />
-  </span>
-  ${ _('results per page.') }
-
-
-  <a href="javascript: void(0)" title="${ _('Next') }">
-    <span data-bind="text: name, click: $root.collection.toggleSortColumnGridLayout"></span>
-    <i class="fa fa-arrow-right" data-bind="
-        visible: ($root.collection.template.rows() * 1.0 + $data.response.start * 1.0) < $data.response.numFound,
-        click: function() { $root.query.paginate('next') }">
-    </i>
-  </a>  
-
-  <!-- ko if: $data.response.numFound > 0 && $data.response.numFound <= 1000 -->
-  <span class="pull-right">
-    <form method="POST" action="${ url('search:download') }">
-      <input type="hidden" name="collection" data-bind="value: ko.mapping.toJSON($root.collection)"/>
-      <input type="hidden" name="query" data-bind="value: ko.mapping.toJSON($root.query)"/>
-      <button class="btn" type="submit" name="json" title="${ _('Download as JSON') }"><i class="hfo hfo-file-json"></i></button>
-      <button class="btn" type="submit" name="csv" title="${ _('Download as CSV') }"><i class="hfo hfo-file-csv"></i></button>
-      <button class="btn" type="submit" name="xls" title="${ _('Download as Excel') }"><i class="hfo hfo-file-xls"></i></button>
-    </form>
-  </span>
-  <!-- /ko -->
-</div>
-</script>
-
-<script type="text/html" id="histogram-widget">
-  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
-  <!-- /ko -->
-
-  <div class="widget-spinner" data-bind="visible: isLoading()">
-    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-  </div>
-
-  <!-- ko if: $root.getFacetFromQuery(id()) -->
-  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
-    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">      
-      <span data-bind="template: { name: 'facet-toggle' }">
-      </span>
-    </div>  
-
-    <a href="javascript:void(0)" data-bind="click: $root.collection.timeLineZoom"><i class="fa fa-search-minus"></i></a>
-    <span>
-      ${ _('Group By') }
-      <select class="input-medium" data-bind="options: $root.query.multiqs, optionsValue: 'id',optionsText: 'label', value: $root.query.selectedMultiq">
-      </select>      
-    </span>
-
-    <div data-bind="timelineChart: {datum: {counts: counts, extraSeries: extraSeries, widget_id: $parent.id(), label: label}, stacked: $root.collection.getFacetById($parent.id()).properties.stacked(), field: field, label: label, transformer: timelineChartDataTransformer,
-      onSelectRange: function(from, to){ viewModel.collection.selectTimelineFacet({from: from, to: to, cat: field, widget_id: $parent.id()}) },
-      onStateChange: function(state){ $root.collection.getFacetById($parent.id()).properties.stacked(state.stacked); },
-      onClick: function(d){ viewModel.query.selectRangeFacet({count: d.obj.value, widget_id: $parent.id(), from: d.obj.from, to: d.obj.to, cat: d.obj.field}) },
-      onComplete: function(){ viewModel.getWidgetById(id).isLoading(false) }}" />
-  </div>
-  <!-- /ko -->
-</script>
-
-<script type="text/html" id="bar-widget">
-  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
-  <!-- /ko -->
-
-  <div class="widget-spinner" data-bind="visible: isLoading()">
-    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-  </div>
-
-  <!-- ko if: $root.getFacetFromQuery(id()) -->
-  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
-    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">      
-      <span data-bind="template: { name: 'facet-toggle' }">
-      </span>
-    </div> 
-
-    <div data-bind="barChart: {datum: {counts: counts, widget_id: $parent.id(), label: label}, stacked: false, field: field, label: label,
-      transformer: barChartDataTransformer,
-      onStateChange: function(state){ console.log(state); },
-      onClick: function(d){ viewModel.query.selectRangeFacet({count: d.obj.value, widget_id: d.obj.widget_id, from: d.obj.from, to: d.obj.to, cat: d.obj.field}) },
-      onSelectRange: function(from, to){ viewModel.collection.selectTimelineFacet({from: from, to: to, cat: field, widget_id: $parent.id()}) },
-      onComplete: function(){ viewModel.getWidgetById(id).isLoading(false) } }"
-    />
-  </div>
-  <!-- /ko -->
-</script>
-
-<script type="text/html" id="line-widget">
-  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
-  <!-- /ko -->
-
-  <div class="widget-spinner" data-bind="visible: isLoading()">
-    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-  </div>
-
-  <!-- ko if: $root.getFacetFromQuery(id()) -->
-  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
-    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">
-      <span data-bind="template: { name: 'facet-toggle' }">
-      </span>
-    </div>
-
-    <div data-bind="lineChart: {datum: {counts: counts, widget_id: $parent.id(), label: label}, field: field, label: label,
-      transformer: lineChartDataTransformer,      
-      onClick: function(d){ viewModel.query.selectRangeFacet({count: d.obj.value, widget_id: d.obj.widget_id, from: d.obj.from, to: d.obj.to, cat: d.obj.field}) },
-      onSelectRange: function(from, to){ viewModel.collection.selectTimelineFacet({from: from, to: to, cat: field, widget_id: $parent.id()}) },
-      onComplete: function(){ viewModel.getWidgetById(id).isLoading(false) } }"
-    />
-  </div>
-  <!-- /ko -->
-</script>
-
-
-<script type="text/html" id="pie-widget">
-  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
-  <!-- /ko -->
-
-  <!-- ko if: $root.getFacetFromQuery(id()) -->
-  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
-    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">
-      <span data-bind="template: { name: 'facet-toggle' }">
-      </span>
-    </div>
-
-    <div data-bind="with: $root.collection.getFacetById($parent.id())">
-      <!-- ko if: type() == 'range' -->
-      <div data-bind="pieChart: {data: {counts: $parent.counts, widget_id: $parent.id}, field: field, fqs: $root.query.fqs,
-        transformer: rangePieChartDataTransformer,
-        maxWidth: 250,
-        onClick: function(d){ viewModel.query.selectRangeFacet({count: d.data.obj.value, widget_id: d.data.obj.widget_id, from: d.data.obj.from, to: d.data.obj.to, cat: d.data.obj.field}) }, 
-        onComplete: function(){ viewModel.getWidgetById($parent.id).isLoading(false)} }" />
-      <!-- /ko -->
-      <!-- ko if: type() != 'range' -->
-      <div data-bind="pieChart: {data: {counts: $parent.counts, widget_id: $parent.id}, field: field, fqs: $root.query.fqs,
-        transformer: pieChartDataTransformer,
-        maxWidth: 250,
-        onClick: function(d){viewModel.query.toggleFacet({facet: d.data.obj, widget_id: d.data.obj.widget_id})},
-        onComplete: function(){viewModel.getWidgetById($parent.id).isLoading(false)}}" />
-      <!-- /ko -->
-    </div>    
-  </div>
-  <!-- /ko -->
-  <div class="widget-spinner" data-bind="visible: isLoading()">
-    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-  </div>
-</script>
-
-<script type="text/html" id="filter-widget">
-  <div data-bind="visible: $root.query.fqs().length == 0" style="margin-top: 10px">${_('There are currently no filters applied.')}</div>
-  <div data-bind="foreach: { data: $root.query.fqs, afterRender: function(){ isLoading(false); } }">
-    <!-- ko if: $data.type() == 'field' -->
-    <div class="filter-box">
-      <a href="javascript:void(0)" class="pull-right" data-bind="click: function(){ viewModel.query.removeFilter($data); viewModel.search() }"><i class="fa fa-times"></i></a>
-      <strong>${_('field')}</strong>:
-      <span data-bind="text: $data.field"></span>
-      <br/>
-      <strong>${_('value')}</strong>:
-      <span data-bind="text: $data.filter"></span>
-    </div>
-    <!-- /ko -->
-    <!-- ko if: $data.type() == 'range' -->
-    <div class="filter-box">
-      <a href="javascript:void(0)" class="pull-right" data-bind="click: function(){ viewModel.query.removeFilter($data); viewModel.search() }"><i class="fa fa-times"></i></a>
-      <strong>${_('field')}</strong>:
-      <span data-bind="text: $data.field"></span>
-      <br/>
-      <span data-bind="foreach: $data.properties" style="font-weight: normal">
-        <strong>${_('from')}</strong>: <span data-bind="text: $data.from"></span>
-        <br/>
-        <strong>${_('to')}</strong>: <span data-bind="text: $data.from"></span>
-      </span>
-    </div>
-    <!-- /ko -->
-  </div>
-  <div class="clearfix"></div>
-  <div class="widget-spinner" data-bind="visible: isLoading() &&  $root.query.fqs().length > 0">
-    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-  </div>
-</script>
-
-<script type="text/html" id="map-widget">
-  <!-- ko ifnot: $root.getFacetFromQuery(id()) -->
-  <!-- /ko -->
-
-  <!-- ko if: $root.getFacetFromQuery(id()) -->
-  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id())">
-    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">
-      ${ _('Scope') }: 
-      <select data-bind="selectedOptions: properties.scope" class="input-small">
-        <option value="world">${ _("World") }</option>
-        <option value="usa">${ _("USA") }</option>
-      </select>
-      <span data-bind="template: { name: 'facet-toggle' }">
-      </span>
-    </div>
-    <div data-bind="with: $root.collection.getFacetById($parent.id())">
-      <div data-bind="mapChart: {data: {counts: $parent.counts, scope: $root.collection.getFacetById($parent.id).properties.scope()},
-        transformer: mapChartDataTransformer,
-        maxWidth: 750,
-        onClick: function(d){ viewModel.query.toggleFacet({facet: d, widget_id: $parent.id}) },
-        onComplete: function(){ viewModel.getWidgetById($parent.id).isLoading(false)} }" />
-    </div>
-  </div>
-  <!-- /ko -->
-  <div class="widget-spinner" data-bind="visible: isLoading()">
-    <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-    <!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-  </div>
-</script>
-
-<div id="addFacetDemiModal" class="demi-modal hide" data-backdrop="false">
-  <div class="modal-body">
-    <a href="javascript: void(0)" data-dismiss="modal" data-bind="click: addFacetDemiModalFieldCancel" class="pull-right"><i class="fa fa-times"></i></a>
-    <div style="float: left; margin-right: 10px;text-align: center">
-      <input id="addFacetInput" type="text" data-bind="value: $root.collection.template.fieldsModalFilter, valueUpdate:'afterkeydown'" placeholder="${_('Filter fields')}" class="input" style="float: left" /><br/>
-    </div>
-    <div>
-      <ul data-bind="foreach: $root.collection.template.filteredModalFields().sort(function (l, r) { return l.name() > r.name() ? 1 : -1 }), visible: $root.collection.template.filteredModalFields().length > 0"
-          class="unstyled inline fields-chooser" style="height: 100px; overflow-y: auto">
-        <li data-bind="click: addFacetDemiModalFieldPreview">
-          <span class="badge badge-info"><span data-bind="text: name(), attr: {'title': type()}"></span>
-          </span>
-        </li>
-      </ul>
-      <div class="alert alert-info inline" data-bind="visible: $root.collection.template.filteredModalFields().length == 0" style="margin-left: 124px;height: 42px;line-height: 42px">
-        ${_('There are no fields matching your search term.')}
-      </div>
-    </div>
-  </div>
-</div>
-
-<div id="genericLoader" style="display: none">
-<!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
-<!--[if IE]><img src="/static/art/spinner.gif" /><![endif]-->
-</div>
-
-<script id="document-details" type="x-tmpl-mustache">
-<div class="document-details">
-  <table>
-    <tbody>
-    {{#properties}}
-      <tr>
-        <th style="text-align: left; white-space: nobreak; vertical-align:top">{{key}}</th>
-        <td width="100%">{{value}}</td>
-      </tr>
-      {{/properties}}
-    </tbody>
-  </table>
-  </div>
-</script>
-
-## Extra code for style and custom JS
-<span data-bind="html: $root.collection.template.extracode"></span>
-
-<link rel="stylesheet" href="/search/static/css/search.css">
-<link rel="stylesheet" href="/static/ext/css/hue-filetypes.css">
-<link rel="stylesheet" href="/static/ext/css/leaflet.css">
-<link rel="stylesheet" href="/static/ext/css/hue-charts.css">
-<link rel="stylesheet" href="/static/css/freshereditor.css">
-<link rel="stylesheet" href="/static/ext/css/codemirror.css">
-<link rel="stylesheet" href="/static/ext/css/bootstrap-editable.css">
-<link rel="stylesheet" href="/static/ext/css/bootstrap-slider.min.css">
-<link rel="stylesheet" href="/static/css/bootstrap-spinedit.css">
-<link rel="stylesheet" href="/static/ext/css/nv.d3.min.css">
-<link rel="stylesheet" href="/static/ext/chosen/chosen.min.css">
-
-<script src="/search/static/js/search.utils.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/knockout.mapping-2.3.2.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/knockout-sortable.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/bootstrap-editable.min.js"></script>
-<script src="/static/ext/js/bootstrap-slider.min.js"></script>
-<script src="/static/js/bootstrap-spinedit.js"></script>
-<script src="/static/js/ko.editable.js"></script>
-<script src="/static/ext/js/shortcut.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/js/freshereditor.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/codemirror-3.11.js"></script>
-<script src="/static/ext/js/moment.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/codemirror-xml.js"></script>
-<script src="/static/ext/js/mustache.js"></script>
-<script src="/static/ext/js/jquery/plugins/jquery-ui-1.10.4.draggable-droppable-sortable.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/jquery/plugins/jquery.flot.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/jquery/plugins/jquery.flot.categories.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/leaflet/leaflet.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/chosen/chosen.jquery.min.js" type="text/javascript" charset="utf-8"></script>
-
-<script src="/search/static/js/search.ko.js" type="text/javascript" charset="utf-8"></script>
-
-<script src="/static/js/hue.geo.js"></script>
-<script src="/static/js/hue.colors.js"></script>
-
-<script src="/static/ext/js/d3.v3.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/nv.d3.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/topojson.v1.min.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/topo/world.topo.js" type="text/javascript" charset="utf-8"></script>
-<script src="/static/ext/js/topo/usa.topo.js" type="text/javascript" charset="utf-8"></script>
-
-<script src="/search/static/js/nv.d3.datamaps.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/nv.d3.legend.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/nv.d3.multiBarWithBrushChart.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/nv.d3.lineWithBrushChart.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/nv.d3.growingDiscreteBar.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/nv.d3.growingDiscreteBarChart.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/nv.d3.growingMultiBar.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/nv.d3.growingMultiBarChart.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/nv.d3.growingPie.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/nv.d3.growingPieChart.js" type="text/javascript" charset="utf-8"></script>
-<script src="/search/static/js/charts.ko.js" type="text/javascript" charset="utf-8"></script>
-
-<script src="/static/ext/js/less-1.7.0.min.js" type="text/javascript" charset="utf-8"></script>
-
-<style type="text/css">
-  .dashboard .container-fluid {
-    padding: 6px;
-  }
-
-  .row-container {
-    width: 100%;
-    min-height: 70px;
-  }
-
-  .row-container.is-editing {
-    border: 1px solid #e5e5e5;
-  }
-
-  .ui-sortable {
-    background-color: #F3F3F3;
-    min-height: 100px;
-  }
-
-  .ui-sortable h2 {
-    padding-left: 10px!important;
-  }
-
-  .ui-sortable h2 ul {
-    float: left;
-    margin-right: 10px;
-    font-size: 14px;
-  }
-
-  .ui-sortable-disabled {
-    background-color: #FFF;
-  }
-
-  .card-column {
-    border: none;
-    min-height: 400px!important;
-  }
-
-  .card-widget {
-    padding-top: 0;
-    border: 0;
-    min-height: 100px;
-  }
-
-  .card-widget .card-heading {
-    font-size: 12px!important;
-    font-weight: bold!important;
-    line-height: 24px!important;
-  }
-
-  .card-widget .card-body {
-    margin-top: 0;
-  }
-
-  .card-toolbar {
-    margin: 0;
-    padding: 4px;
-    padding-top: 0;
-    top: 70px;
-    position: fixed;
-    width: 100%;
-    z-index: 1000;
-  }
-
-  .row-header {
-    background-color: #F6F6F6;
-    display: inline;
-    padding: 3px;
-    border: 1px solid #e5e5e5;
-    border-bottom: none;
-  }
-
-  .row-highlight {
-    background-color: #DDD;
-    min-height: 100px;
-  }
-
-  #emptyDashboard {
-    position: absolute;
-    right: 164px;
-    top: 80px;
-    color: #666;
-    font-size: 20px;
-  }
-
-  .emptyRow {
-    margin-top: 10px;
-    margin-left: 140px;
-    color: #666;
-    font-size: 18px;
-  }
-
-  .preview-row {
-    background-color: #DDD;
-    min-height: 400px!important;
-    margin-top: 30px;
-  }
-
-  .toolbar-label {
-    float: left;
-    font-weight: bold;
-    color: #999;
-    padding-left: 8px;
-    padding-top: 24px;
-  }
-
-  .draggable-widget {
-    width: 60px;
-    text-align: center;
-    float: left;
-    border: 1px solid #CCC;
-    margin-top: 10px;
-    margin-left: 10px;
-    cursor: move;
-  }
-
-  .draggable-widget.disabled {
-    cursor: default;
-  }
-
-  .draggable-widget a {
-    font-size: 28px;
-    line-height: 46px;
-  }
-
-  .draggable-widget.disabled a {
-    cursor: default;
-    color: #CCC;
-  }
-
-  .layout-container {
-    width: 100px;
-    float: left;
-    margin-top: 10px;
-    margin-left: 10px;
-  }
-
-  .layout-box {
-    float: left;
-    height: 48px;
-    background-color: #DDD;
-    text-align: center;
-  }
-
-  .layout-box i {
-    color: #333;
-    font-size: 28px;
-    line-height: 48px;
-  }
-
-  .layout-container:hover .layout-box {
-    background-color: #CCC;
-  }
-
-  .with-top-margin {
-    margin-top: 60px;
-  }
-
-  .ui-sortable .card-heading {
-    -webkit-touch-callout: none;
-    -webkit-user-select: none;
-    -khtml-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
-  }
-
-  .search-bar {
-    padding-top: 6px;
-    padding-bottom: 6px;
-  }
-
-  .widget-settings-section {
-    display: none;
-  }
-
-  em {
-    font-weight: bold;
-    background-color: yellow;
-  }
-
-  .nvd3 .nv-brush .extent {
-    fill-opacity: .225!important;
-  }
-
-  .nvd3 .nv-legend .disabled rect {
-    fill-opacity: 0;
-  }
-
-
-  .fields-chooser li {
-    cursor: pointer;
-    margin-bottom: 10px;
-  }
-
-  .fields-chooser li .badge {
-    font-weight: normal;
-    font-size: 12px;
-  }
-
-  .widget-spinner {
-    padding: 10px;
-    font-size: 80px;
-    color: #CCC;
-    text-align: center;
-  }
-
-  .card {
-    margin: 0;
-  }
-
-  .badge-left {
-    border-radius: 9px 0px 0px 9px;
-    padding-right: 5px;
-  }
-
-  .badge-right {
-    border-radius: 0px 9px 9px 0px;
-    padding-left: 5px;
-  }
-
-  .trash-filter {
-    cursor: pointer;
-  }
-
-  .move-widget {
-    cursor: move;
-  }
-
-  body.modal-open {
-      overflow: auto!important;
-  }
-
-  .editable-click {
-    cursor: pointer;
-  }
-
-  .CodeMirror {
-    border: 1px dotted #DDDDDD;
-  }
-
-  [contenteditable=true] {
-    border: 1px dotted #DDDDDD;
-    outline: 0;
-    margin-top: 20px;
-    margin-bottom: 20px;
-    min-height: 150px;
-  }
-
-  [contenteditable=true] [class*="span"], .tmpl [class*="span"] {
-    background-color: #eee;
-    -webkit-border-radius: 3px;
-    -moz-border-radius: 3px;
-    border-radius: 3px;
-    min-height: 40px;
-    line-height: 40px;
-    background-color: #F3F3F3;
-    border: 2px dashed #DDD;
-  }
-
-  .tmpl {
-    margin: 10px;
-    height: 60px;
-  }
-
-  .tmpl [class*="span"] {
-    color: #999;
-    font-size: 12px;
-    text-align: center;
-    font-weight: bold;
-  }
-
-  .preview-row:nth-child(odd) {
-    background-color: #f9f9f9;
-  }
-
-  .editor-title {
-    font-weight: bold;
-    color: #262626;
-    border-bottom: 1px solid #338bb8;
-  }
-
-  .add-row {
-    background-color: #F6F6F6;
-    min-height: 36px;
-    border: 2px dashed #DDD;
-    text-align: center;
-    padding: 4px;
-  }
-
-  .add-row:before {
-    color:#DDD;
-    display: inline-block;
-    font-family: FontAwesome;
-    font-style: normal;
-    font-weight: normal;
-    font-size: 24px;
-    line-height: 1;
-    -webkit-font-smoothing: antialiased;
-    -moz-osx-font-smoothing: grayscale;
-    content: "\f055";
-  }
-
-  .add-row-highlight {
-    min-height: 10px;
-    background-color:#CCC;
-  }
-
-  .document-details {
-    background-color: #F6F6F6;
-    padding: 10px;
-    border: 1px solid #e5e5e5;
-  }
-
-  .result-row:nth-child(even) {
-    background-color: #F6F6F6;
-  }
-
-  .demi-modal {
-    min-height: 80px;
-  }
-
-  .filter-box {
-    float: left;
-    margin-right: 10px;
-    margin-bottom: 10px;
-    background-color: #F6F6F6;
-    padding: 5px;
-    border:1px solid #d8d8d8;
-    -webkit-border-radius: 3px;
-    -moz-border-radius: 3px;
-    border-radius: 3px;
-  }
-
-  .spinedit-pagination div.spinedit .fa-chevron-up {
-    top: -7px;
-  }
-
-  .spinedit-pagination div.spinedit .fa-chevron-down {
-    top: 7px;
-    left: -4px;
-  }
-
-</style>
-
-<script type="text/javascript" charset="utf-8">
-var viewModel;
-
-nv.dev = false;
-
-var lastWindowScrollPosition = 0;
-
-function pieChartDataTransformer(data) {
-  var _data = [];
-  $(data.counts).each(function (cnt, item) {
-    item.widget_id = data.widget_id;
-    _data.push({
-      label: item.value,
-      value: item.count,
-      obj: item
-    });
-  });
-  return _data;
-}
-
-function rangePieChartDataTransformer(data) {
-  var _data = [];
-  $(data.counts).each(function (cnt, item) {
-    item.widget_id = data.widget_id;
-    _data.push({
-      label: item.from + ' - ' + item.to,
-      from: item.from,
-      to: item.to,
-      value: item.value,
-      obj: item
-    });
-  });
-  return _data;
-}
-
-function barChartDataTransformer(rawDatum) {
-  var _datum = [];
-  var _data = [];
-  $(rawDatum.counts).each(function (cnt, item) {
-    item.widget_id = rawDatum.widget_id;
-    if (typeof item.from != "undefined"){
-      _data.push({
-        series: 0,
-        x: item.from,
-        x_end: item.to,
-        y: item.value,
-        obj: item
-      });
-    }
-    else {
-      _data.push({
-        series: 0,
-        x: item.value,
-        y: item.count,
-        obj: item
-      });
-    }
-  });
-  _datum.push({
-    key: rawDatum.label,
-    values: _data
-  });
-  return _datum;
-}
-
-function lineChartDataTransformer(rawDatum) {
-  var _datum = [];
-  var _data = [];
-  $(rawDatum.counts).each(function (cnt, item) {
-    item.widget_id = rawDatum.widget_id;
-    if (typeof item.from != "undefined"){
-      _data.push({
-        series: 0,
-        x: item.from,
-        x_end: item.to,
-        y: item.value,
-        obj: item
-      });
-    }
-    else {
-      _data.push({
-        series: 0,
-        x: item.value,
-        y: item.count,
-        obj: item
-      });
-    }
-  });
-  _datum.push({
-    key: rawDatum.label,
-    values: _data
-  });
-  return _datum;
-}
-
-function timelineChartDataTransformer(rawDatum) {
-  var _datum = [];
-  var _data = [];
-
-  $(rawDatum.counts).each(function (cnt, item) {
-    _data.push({
-      series: 0,
-      x: new Date(moment(item.from).valueOf()),
-      y: item.value,
-      obj: item
-    });
-  });
-  
-  _datum.push({
-    key: rawDatum.label,
-    values: _data
-  });
-  
-
-  // If multi query
-  $(rawDatum.extraSeries).each(function (cnt, item) {
-    if (cnt == 0) {
-      _datum = [];
-    }
-    var _data = [];
-    $(item.counts).each(function (cnt, item) {
-      _data.push({
-        series: cnt + 1,
-        x: new Date(moment(item.from).valueOf()),
-        y: item.value,
-        obj: item
-      });
-    });      
-
-    _datum.push({
-      key: item.label,
-      values: _data
-    });
-  });
-  
-  return _datum;
-}
-
-function mapChartDataTransformer(data) {
-  var _data = [];
-  $(data.counts).each(function (cnt, item) {
-    _data.push({
-      label: item.value,
-      value: item.count,
-      obj: item
-    });
-  });
-  return _data;
-}
-
-function toggleDocDetails(doc){
-  var _docRow = $("#doc_" + doc[viewModel.collection.idField()]);
-  if (_docRow.data("expanded") != null && _docRow.data("expanded")){
-    $("#doc_" + doc[viewModel.collection.idField()] + "_details").parent().hide();
-    _docRow.find(".fa-caret-down").removeClass("fa-caret-down").addClass("fa-caret-right");
-    _docRow.data("expanded", false);
-  }
-  else {
-    _docRow.data("expanded", true);
-    var _detailsRow = $("#doc_" + doc[viewModel.collection.idField()] + "_details");
-    if (_detailsRow.length > 0){
-      _detailsRow.parent().show();
-    }
-    else {
-      var _newRow = $("<tr>");
-      var _newCell = $("<td>").attr("colspan", _docRow.find("td").length).attr("id", "doc_" + doc[viewModel.collection.idField()] + "_details").html($("#genericLoader").html());
-      _newCell.appendTo(_newRow);
-      _newRow.insertAfter(_docRow);
-      viewModel.getDocument(doc);
-    }
-    _docRow.find(".fa-caret-right").removeClass("fa-caret-right").addClass("fa-caret-down");
-  }
-}
-
-function resizeFieldsList() {
-  $(".fields-list").css("max-height", Math.max($("#result-container").height(), 230));
-}
-
-$(document).ready(function () {
-
-  var _resizeTimeout = -1;
-  $(window).resize(function(){
-    window.clearTimeout(_resizeTimeout);
-    window.setTimeout(function(){
-      resizeFieldsList();
-    }, 200);
-  });
-
-  $(document).on("showDoc", function(e, doc){
-    viewModel.collection.selectedDocument(doc);
-    var _docDetailsRow = $("#doc_" + doc[viewModel.collection.idField()] + "_details");
-    var _doc = {
-      properties: []
-    };
-    for (var i=0; i< Object.keys(doc).length; i++){
-      _doc.properties.push({
-        key: Object.keys(doc)[i],
-        value: doc[Object.keys(doc)[i]]
-      });
-    }
-    var template = $("#document-details").html();
-    Mustache.parse(template);
-    var rendered = Mustache.render(template, _doc);
-    _docDetailsRow.html(rendered);
-  });
-
-  $(document).on("click", ".widget-settings-pill", function(){
-    $(this).parents(".card-body").find(".widget-section").hide();
-    $(this).parents(".card-body").find(".widget-settings-section").show();
-    $(this).parent().siblings().removeClass("active");
-    $(this).parent().addClass("active");
-  });
-
-  $(document).on("click", ".widget-editor-pill", function(){
-    $(this).parents(".card-body").find(".widget-section").hide();
-    $(this).parents(".card-body").find(".widget-editor-section").show();
-    $(this).parent().siblings().removeClass("active");
-    $(this).parent().addClass("active");
-  });
-
-  $(document).on("click", ".widget-html-pill", function(){
-    $(this).parents(".card-body").find(".widget-section").hide();
-    $(this).parents(".card-body").find(".widget-html-section").show();
-    $(document).trigger("refreshCodemirror");
-    $(this).parent().siblings().removeClass("active");
-    $(this).parent().addClass("active");
-  });
-
-  $(document).on("click", ".widget-css-pill", function(){
-    $(this).parents(".card-body").find(".widget-section").hide();
-    $(this).parents(".card-body").find(".widget-css-section").show();
-    $(document).trigger("refreshCodemirror");
-    $(this).parent().siblings().removeClass("active");
-    $(this).parent().addClass("active");
-  });
-
-  ko.bindingHandlers.slideVisible = {
-    init: function (element, valueAccessor) {
-      var value = valueAccessor();
-      $(element).toggle(ko.unwrap(value));
-    },
-    update: function (element, valueAccessor) {
-      var value = valueAccessor();
-      ko.unwrap(value) ? $(element).slideDown(100) : $(element).slideUp(100);
-    }
-  };
-
-
-  ko.extenders.numeric = function (target, precision) {
-    var result = ko.computed({
-      read: target,
-      write: function (newValue) {
-        var current = target(),
-          roundingMultiplier = Math.pow(10, precision),
-          newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
-          valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
-
-        if (valueToWrite !== current) {
-          target(valueToWrite);
-        } else {
-          if (newValue !== current) {
-            target.notifySubscribers(valueToWrite);
-          }
-        }
-      }
-    }).extend({ notify: 'always' });
-    result(target());
-    return result;
-  };
-
-  ko.bindingHandlers.freshereditor = {
-    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
-      var _el = $(element);
-      var options = $.extend(valueAccessor(), {});
-      _el.html(options.data());
-      _el.freshereditor({
-        excludes: ['strikethrough', 'removeFormat', 'insertorderedlist', 'justifyfull', 'insertheading1', 'insertheading2', 'superscript', 'subscript']
-      });
-      _el.freshereditor("edit", true);
-      _el.on("mouseup", function () {
-        storeSelection();
-        updateValues();
-      });
-
-      var sourceDelay = -1;
-      _el.on("keyup", function () {
-        clearTimeout(sourceDelay);
-        storeSelection();
-        sourceDelay = setTimeout(function () {
-          updateValues();
-        }, 100);
-      });
-
-      $(".chosen-select").chosen({
-        disable_search_threshold: 10,
-        width: "75%"
-      });
-
-      $(document).on("addFieldToVisual", function(e, field){
-        _el.focus();
-        pasteHtmlAtCaret("{{" + field.name() + "}}");
-      });
-
-      $(document).on("addFunctionToVisual", function(e, fn){
-        _el.focus();
-        pasteHtmlAtCaret(fn);
-      });
-
-      function updateValues(){
-        $("[data-template]")[0].editor.setValue(stripHtmlFromFunctions(_el.html()));
-        valueAccessor().data(_el.html());
-      }
-
-      function storeSelection() {
-        if (window.getSelection) {
-          // IE9 and non-IE
-          sel = window.getSelection();
-          if (sel.getRangeAt && sel.rangeCount) {
-            range = sel.getRangeAt(0);
-            _el.data("range", range);
-          }
-        }
-        else if (document.selection && document.selection.type != "Control") {
-          // IE < 9
-          _el.data("selection", document.selection);
-        }
-      }
-
-    function pasteHtmlAtCaret(html) {
-      var sel, range;
-      if (window.getSelection) {
-        // IE9 and non-IE
-        sel = window.getSelection();
-        if (sel.getRangeAt && sel.rangeCount) {
-          if (_el.data("range")) {
-            range = _el.data("range");
-          }
-          else {
-            range = sel.getRangeAt(0);
-          }
-          range.deleteContents();
-
-          // Range.createContextualFragment() would be useful here but is
-          // non-standard and not supported in all browsers (IE9, for one)
-          var el = document.createElement("div");
-          el.innerHTML = html;
-          var frag = document.createDocumentFragment(), node, lastNode;
-          while ((node = el.firstChild)) {
-            lastNode = frag.appendChild(node);
-          }
-          range.insertNode(frag);
-
-          // Preserve the selection
-          if (lastNode) {
-            range = range.cloneRange();
-            range.setStartAfter(lastNode);
-            range.collapse(true);
-            sel.removeAllRanges();
-            sel.addRange(range);
-          }
-        }
-      } else if (document.selection && document.selection.type != "Control") {
-        // IE < 9
-        if (_el.data("selection")) {
-          _el.data("selection").createRange().pasteHTML(html);
-        }
-        else {
-          document.selection.createRange().pasteHTML(html);
-        }
-      }
-    }
-    }
-  };
-
-  ko.bindingHandlers.slider = {
-    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
-      var _el = $(element);
-      var _options = $.extend(valueAccessor(), {});
-      _el.slider({
-        min: _options.min ? _options.min : 1,
-        max: _options.max ? _options.max : 10,
-        step: _options.step ? _options.step : 1,
-        handle: _options.handle ? _options.handle : 'circle',
-        value: _options.data(),
-        tooltip: 'always'
-      });
-      _el.on("slide", function (e) {
-        _options.data(e.value);
-      });
-    },
-    update: function (element, valueAccessor, allBindingsAccessor) {
-      var _options = $.extend(valueAccessor(), {});
-      $(element).slider("setValue", _options.data());
-    }
-  }
-
-  ko.bindingHandlers.spinedit = {
-    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
-      $(element).spinedit({
-        minimum: 0,
-        maximum: 10000,
-        step: 5,
-        value: ko.unwrap(valueAccessor()),
-        numberOfDecimals: 0
-      });
-      $(element).on("valueChanged", function (e) {
-        valueAccessor()(e.value);
-      });
-    },
-    update: function (element, valueAccessor, allBindingsAccessor) {
-      $(element).spinedit("setValue", ko.unwrap(valueAccessor()));
-    }
-  }
-
-  ko.bindingHandlers.codemirror = {
-    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
-      var options = $.extend(valueAccessor(), {});
-      var editor = CodeMirror.fromTextArea(element, options);
-      element.editor = editor;
-      editor.setValue(options.data());
-      editor.refresh();
-      var wrapperElement = $(editor.getWrapperElement());
-
-      $(document).on("refreshCodemirror", function(){
-        editor.setSize("100%", 300);
-        editor.refresh();
-      });
-
-      $(document).on("addFieldToSource", function(e, field){
-        if ($(element).data("template")){
-          editor.replaceSelection("{{" + field.name() + "}}");
-        }
-      });
-
-      $(document).on("addFunctionToSource", function(e, fn){
-        if ($(element).data("template")){
-          editor.replaceSelection(fn);
-        }
-      });
-
-      $(".chosen-select").chosen({
-        disable_search_threshold: 10,
-        width: "75%"
-      });
-      $('.chosen-select').trigger('chosen:updated');
-
-      var sourceDelay = -1;
-      editor.on("change", function (cm) {
-        clearTimeout(sourceDelay);
-        var _cm = cm;
-        sourceDelay = setTimeout(function () {
-          var _enc = $("<span>").html(_cm.getValue());
-          if (_enc.find("style").length > 0){
-            var parser = new less.Parser();
-            $(_enc.find("style")).each(function(cnt, item){
-              var _less = "#result-container {" + $(item).text() + "}";
-              try {
-                parser.parse(_less, function (err, tree) {
-                  $(item).text(tree.toCSS());
-                });
-              }
-              catch (e){}
-            });
-            valueAccessor().data(_enc.html());
-          }
-          else {
-            valueAccessor().data(_cm.getValue());
-          }
-          if ($(".widget-html-pill").parent().hasClass("active")){
-            $("[contenteditable=true]").html(stripHtmlFromFunctions(valueAccessor().data()));
-          }
-        }, 100);
-      });
-
-      ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
-        wrapperElement.remove();
-      });
-    },
-    update: function (element, valueAccessor, allBindingsAccessor) {
-      var editor = element.editor;
-      editor.refresh();
-    }
-  };
-
-
-  viewModel = new SearchViewModel(${ collection.get_c(user) | n,unicode }, ${ query | n,unicode }, ${ initial | n,unicode });
-  ko.applyBindings(viewModel);
-
-  viewModel.init(function(data){
-    $(".chosen-select").trigger("chosen:updated");
-  });
-  viewModel.isRetrievingResults.subscribe(function(value){
-    if (!value){
-      resizeFieldsList();
-    }
-  });
-
-  $("#addFacetDemiModal").on("hidden", function () {
-    if (typeof selectedWidget.hasBeenSelected == "undefined"){
-      addFacetDemiModalFieldCancel();
-    }
-  });
-
-});
-
-  function toggleGridFieldsSelection() {
-    if (viewModel.collection.template.fields().length > 0) {
-      viewModel.collection.template.fieldsSelected([])
-    }
-    else {
-      var _fields = [];
-      $.each(viewModel.collection.fields(), function (index, field) {
-        _fields.push(field.name());
-      });
-      viewModel.collection.template.fieldsSelected(_fields);
-    }
-  }
-
-  var selectedWidget = null;
-  function showAddFacetDemiModal(widget) {
-    if (["resultset-widget", "html-resultset-widget", "filter-widget"].indexOf(widget.widgetType()) == -1) {      
-      viewModel.collection.template.fieldsModalFilter("");
-      viewModel.collection.template.fieldsModalType(widget.widgetType());
-      viewModel.collection.template.fieldsModalFilter.valueHasMutated();
-      $('#addFacetInput').typeahead({
-          'source': viewModel.collection.template.availableWidgetFieldsNames(), 
-          'updater': function(item) {
-              addFacetDemiModalFieldPreview({'name': function(){return item}});
-              return item;
-           }
-      });
-      selectedWidget = widget;
-      $("#addFacetDemiModal").modal("show");
-      $("#addFacetDemiModal input[type='text']").focus();
-    }
-  }
-
-
-  function addFacetDemiModalFieldPreview(field) {
-    var _existingFacet = viewModel.collection.getFacetById(selectedWidget.id());
-    if (selectedWidget != null) {
-      selectedWidget.hasBeenSelected = true;
-      selectedWidget.isLoading(true);
-      viewModel.collection.addFacet({'name': field.name(), 'widget_id': selectedWidget.id(), 'widgetType': selectedWidget.widgetType()});
-      if (_existingFacet != null) {
-        _existingFacet.label(field.name());
-        _existingFacet.field(field.name());
-      }
-      $("#addFacetDemiModal").modal("hide");
-    }
-  }
-  
-  function addFacetDemiModalFieldCancel() {
-    viewModel.removeWidget(selectedWidget);
-  }
-
-</script>
-
-${ commonfooter(messages) | n,unicode }

+ 0 - 43
apps/search/src/search/templates/utils.inc.mako

@@ -1,43 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-
-<%def name="is_selected(section, matcher)">
-  <%
-    if section == matcher:
-      return "active"
-    else:
-      return ""
-  %>
-</%def>
-
-<%def name="render_field(field, show_label=True, extra_attrs={})">
-  % if not field.is_hidden:
-    <% group_class = field.errors and "error" or "" %>
-    <div class="control-group ${group_class}"
-      rel="popover" data-original-title="${ field.label }" data-content="${ field.help_text }">
-      % if show_label:
-        <label class="control-label">${ field.label }</label>
-      % endif
-      <div class="controls">
-        <% field.field.widget.attrs.update(extra_attrs) %>
-        ${ field | n,unicode }
-        % if field.errors:
-          <span class="help-inline">${ field.errors | n,unicode }</span>
-        % endif
-      </div>
-    </div>
-  %endif
-</%def>

+ 3 - 18
apps/search/src/search/urls.py

@@ -25,24 +25,10 @@ urlpatterns = patterns('search.views',
   url(r'^browse/(?P<name>\w+)', 'browse', name='browse'),
   url(r'^download$', 'download', name='download'),
   
-  url(r'^dashboard$', 'dashboard', name='dashboard'),
-
-  # All admin is deprecated
   url(r'^admin/collections$', 'admin_collections', name='admin_collections'),
 
-  url(r'^admin/collections_create_manual$', 'admin_collections_create_manual', name='admin_collections_create_manual'),
-  url(r'^admin/collections_create_file$', 'admin_collections_create_file', name='admin_collections_create_file'),
-  url(r'^admin/collections_import$', 'admin_collections_import', name='admin_collections_import'),
-
-  url(r'^admin/collection/(?P<collection_id>\d+)$', 'admin_collection_template', name='admin_collection'),
-  url(r'^admin/collection/(?P<collection_id>\d+)/properties$', 'admin_collection_properties', name='admin_collection_properties'),
-  url(r'^admin/collection/(?P<collection_id>\d+)/template$', 'admin_collection_template', name='admin_collection_template'),
-  url(r'^admin/collection/(?P<collection_id>\d+)/facets$', 'admin_collection_facets', name='admin_collection_facets'),
-  url(r'^admin/collection/(?P<collection_id>\d+)/highlighting$', 'admin_collection_highlighting', name='admin_collection_highlighting'),
-  url(r'^admin/collection/(?P<collection_id>\d+)/sorting$', 'admin_collection_sorting', name='admin_collection_sorting'),
-
   # Ajax
-  url(r'^fields/parse$', 'parse_fields', name='parse_fields'),
+  # Search
   url(r'^suggest/(?P<collection_id>\w+)/(?P<query>\w+)?$', 'query_suggest', name='query_suggest'),
   url(r'^index/fields/dynamic$', 'index_fields_dynamic', name='index_fields_dynamic'),
   url(r'^template/new_facet$', 'new_facet', name='new_facet'),
@@ -51,9 +37,8 @@ urlpatterns = patterns('search.views',
   url(r'^get_timeline$', 'get_timeline', name='get_timeline'),
   url(r'^get_collection', 'get_collection', name='get_collection'),
   
-  # old
-  url(r'^admin/collection/(?P<collection_id>\w+)/schema$', 'admin_collection_schema', name='admin_collection_schema'),
-  url(r'^admin/collection/(?P<collection_id>\w+)/solr_properties$', 'admin_collection_solr_properties', name='admin_collection_solr_properties'),
+  # Admin
+  url(r'^admin/collections_import$', 'admin_collections_import', name='admin_collections_import'),
   url(r'^admin/collection_delete$', 'admin_collection_delete', name='admin_collection_delete'),
   url(r'^admin/collection_copy$', 'admin_collection_copy', name='admin_collection_copy'),
 

+ 8 - 227
apps/search/src/search/views.py

@@ -26,17 +26,13 @@ from django.shortcuts import redirect
 
 from desktop.lib.django_util import render
 from desktop.lib.exceptions_renderable import PopupException
-from desktop.lib import i18n
-
-from beeswax.create_table import _parse_fields, FILE_READERS, DELIMITERS
 
 from search.api import SolrApi, _guess_gap, _zoom_range_facet, _new_range_facet
 from search.conf import SOLR_URL
 from search.data_export import download as export_download
 from search.decorators import allow_admin_only
-from search.forms import QueryForm, CollectionForm
 from search.management.commands import search_setup
-from search.models import Collection, augment_solr_response2, augment_solr_exception
+from search.models import Collection, augment_solr_response, augment_solr_exception
 from search.search_controller import SearchController
 
 from django.utils.encoding import force_unicode
@@ -51,10 +47,6 @@ def initial_collection(request, hue_collections):
   return hue_collections[0].id
 
 
-def dashboard(request):
-  return render('dashboard.mako', request, {})
-
-
 def index(request):
   hue_collections = SearchController(request.user).get_search_collections()
   collection_id = request.GET.get('collection')
@@ -68,7 +60,7 @@ def index(request):
   collection = Collection.objects.get(id=collection_id) # TODO perms HUE-1987
   query = {'qs': [{'q': ''}], 'fqs': [], 'start': 0}
 
-  return render('search2.mako', request, {
+  return render('search.mako', request, {
     'collection': collection,
     'query': query,
     'initial': '{}',    
@@ -84,7 +76,7 @@ def new_search(request):
   collection = Collection(name=collections[0], label=collections[0])
   query = {'qs': [{'q': ''}], 'fqs': [], 'start': 0}
 
-  return render('search2.mako', request, {
+  return render('search.mako', request, {
     'collection': collection,
     'query': query,
     'initial': json.dumps({
@@ -109,7 +101,7 @@ def browse(request, name):
   collection = Collection(name=name, label=name)
   query = {'qs': [{'q': ''}], 'fqs': [], 'start': 0}
 
-  return render('search2.mako', request, {
+  return render('search.mako', request, {
     'collection': collection,
     'query': query,
     'initial': json.dumps({
@@ -138,7 +130,7 @@ def search(request):
   if collection:
     try:      
       response = SolrApi(SOLR_URL.get(), request.user).query2(collection, query)
-      response = augment_solr_response2(response, collection, query)
+      response = augment_solr_response(response, collection, query)
     except RestException, e:
       try:
         response['error'] = json.loads(e.message)['error']['msg']
@@ -183,8 +175,7 @@ def save(request):
   return HttpResponse(json.dumps(response), mimetype="application/json")
 
 
-def download(request):
-  
+def download(request):  
   try:
     file_format = 'csv' if 'csv' in request.POST else 'xls' if 'xls' in request.POST else 'json'
     response = search(request)
@@ -228,58 +219,6 @@ def admin_collections(request, is_redirect=False):
   })
 
 
-@allow_admin_only
-def admin_collections_create_manual(request):
-  return render('admin_collections_create_manual.mako', request, {})
-
-
-@allow_admin_only
-def admin_collections_create_file(request):
-  return render('admin_collections_create_file.mako', request, {})
-
-
-@allow_admin_only
-def admin_collections_create(request):
-  if request.method != 'POST':
-    raise PopupException(_('POST request required.'))
-
-  response = {'status': -1}
-
-  collection = json.loads(request.POST.get('collection', '{}'))
-
-  if collection:
-    searcher = SearchController(request.user)
-    searcher.create_new_collection(collection.get('name', ''), collection.get('fields', []))
-
-    response['status'] = 0
-    response['message'] = _('Page saved!')
-  else:
-    response['message'] = _('Collection missing.')
-
-  return HttpResponse(json.dumps(response), mimetype="application/json")
-
-
-@allow_admin_only
-def admin_collection_update(request):
-  if request.method != 'POST':
-    raise PopupException(_('POST request required.'))
-
-  response = {'status': -1}
-
-  collection = json.loads(request.POST.get('collection', '{}'))
-
-  if collection:
-    hue_collection = Collection.objects.get(id=collection['id'])
-    searcher = SearchController(request.user)
-    searcher.create_new_collection(collection.get('name', ''), collection.get('fields', []))
-
-    response['status'] = 0
-    response['message'] = _('Page saved!')
-  else:
-    response['message'] = _('Collection missing.')
-
-  return HttpResponse(json.dumps(response), mimetype="application/json")
-
 
 @allow_admin_only
 def admin_collections_import(request):
@@ -340,6 +279,7 @@ def admin_collections_import(request):
     else:
       return admin_collections(request, True)
 
+
 @allow_admin_only
 def admin_collection_delete(request):
   if request.method != 'POST':
@@ -368,165 +308,6 @@ def admin_collection_copy(request):
   return HttpResponse(json.dumps(response), mimetype="application/json")
 
 
-@allow_admin_only
-def admin_collection_properties(request, collection_id):
-  hue_collection = Collection.objects.get(id=collection_id)
-  solr_collection = SolrApi(SOLR_URL.get(), request.user).collection_or_core(hue_collection)
-
-  if request.method == 'POST':
-    collection_form = CollectionForm(request.POST, instance=hue_collection, user=request.user)
-    if collection_form.is_valid(): # Check for autocomplete in data?
-      searcher = SearchController(request.user)
-      hue_collection = collection_form.save(commit=False)
-      hue_collection.is_core_only = not searcher.is_collection(hue_collection.name)
-      hue_collection.autocomplete = json.loads(request.POST.get('autocomplete'))
-      hue_collection.save()
-      return redirect(reverse('search:admin_collection_properties', kwargs={'collection_id': hue_collection.id}))
-    else:
-      request.error(_('Errors on the form: %s.') % collection_form.errors)
-  else:
-    collection_form = CollectionForm(instance=hue_collection)
-
-  return render('admin_collection_properties.mako', request, {
-    'solr_collection': solr_collection,
-    'hue_collection': hue_collection,
-    'collection_form': collection_form,
-    'collection_properties': json.dumps(hue_collection.properties_dict)
-  })
-
-
-@allow_admin_only
-def admin_collection_template(request, collection_id):
-  hue_collection = Collection.objects.get(id=collection_id)
-  solr_collection = SolrApi(SOLR_URL.get(), request.user).collection_or_core(hue_collection)
-  sample_data = {}
-
-  if request.method == 'POST':
-    hue_collection.result.update_from_post(request.POST)
-    hue_collection.result.save()
-    return HttpResponse(json.dumps({}), mimetype="application/json")
-
-  solr_query = {}
-  solr_query['collection'] = hue_collection.name
-  solr_query['q'] = ''
-  solr_query['fq'] = ''
-  solr_query['rows'] = 5
-  solr_query['start'] = 0
-  solr_query['facets'] = 0
-
-  try:
-    response = SolrApi(SOLR_URL.get(), request.user).query(solr_query, hue_collection)
-    sample_data = json.dumps(response["response"]["docs"])
-  except PopupException, e:
-    message = e
-    try:
-      message = json.loads(e.message.message)['error']['msg'] # Try to get the core error
-    except:
-      pass
-    request.error(_('No preview available, some facets are invalid: %s') % message)
-    LOG.exception(e)
-
-  return render('admin_collection_template.mako', request, {
-    'solr_collection': solr_collection,
-    'hue_collection': hue_collection,
-    'sample_data': sample_data,
-  })
-
-
-@allow_admin_only
-def admin_collection_facets(request, collection_id):
-  hue_collection = Collection.objects.get(id=collection_id)
-  solr_collection = SolrApi(SOLR_URL.get(), request.user).collection_or_core(hue_collection)
-
-  if request.method == 'POST':
-    hue_collection.facets.update_from_post(request.POST)
-    hue_collection.facets.save()
-    return HttpResponse(json.dumps({}), mimetype="application/json")
-
-  return render('admin_collection_facets.mako', request, {
-    'solr_collection': solr_collection,
-    'hue_collection': hue_collection,
-  })
-
-
-@allow_admin_only
-def admin_collection_sorting(request, collection_id):
-  hue_collection = Collection.objects.get(id=collection_id)
-  solr_collection = SolrApi(SOLR_URL.get(), request.user).collection_or_core(hue_collection)
-
-  if request.method == 'POST':
-    hue_collection.sorting.update_from_post(request.POST)
-    hue_collection.sorting.save()
-    return HttpResponse(json.dumps({}), mimetype="application/json")
-
-  return render('admin_collection_sorting.mako', request, {
-    'solr_collection': solr_collection,
-    'hue_collection': hue_collection,
-  })
-
-
-@allow_admin_only
-def admin_collection_highlighting(request, collection_id):
-  hue_collection = Collection.objects.get(id=collection_id)
-  solr_collection = SolrApi(SOLR_URL.get(), request.user).collection_or_core(hue_collection)
-
-  if request.method == 'POST':
-    hue_collection.result.update_from_post(request.POST)
-    hue_collection.result.save()
-    return HttpResponse(json.dumps({}), mimetype="application/json")
-
-  return render('admin_collection_highlighting.mako', request, {
-    'solr_collection': solr_collection,
-    'hue_collection': hue_collection,
-  })
-
-
-# Ajax below
-
-@allow_admin_only
-def admin_collection_solr_properties(request, collection_id):
-  hue_collection = Collection.objects.get(id=collection_id)
-  solr_collection = SolrApi(SOLR_URL.get(), request.user).collection_or_core(hue_collection)
-
-  content = render('admin_collection_properties_solr_properties.mako', request, {
-    'solr_collection': solr_collection,
-    'hue_collection': hue_collection,
-  }, force_template=True).content
-
-  return HttpResponse(json.dumps({'content': content}), mimetype="application/json")
-
-
-@allow_admin_only
-def admin_collection_schema(request, collection_id):
-  hue_collection = Collection.objects.get(id=collection_id)
-  solr_schema = SolrApi(SOLR_URL.get(), request.user).schema(hue_collection.name)
-
-  content = {
-    'solr_schema': solr_schema.decode('utf-8')
-  }
-  return HttpResponse(json.dumps(content), mimetype="application/json")
-
-
-@allow_admin_only
-def parse_fields(request):
-  result = {'status': -1, 'message': ''}
-
-  try:
-    file_obj = request.FILES.get('collections_file')
-    delim, reader_type, fields_list = _parse_fields(
-                                        'collections_file',
-                                        file_obj,
-                                        i18n.get_site_encoding(),
-                                        [reader.TYPE for reader in FILE_READERS],
-                                        DELIMITERS)
-    result['status'] = 0
-    result['data'] = fields_list
-  except Exception, e:
-    result['message'] = e.message
-
-  return HttpResponse(json.dumps(result), mimetype="application/json")
-
-
 # TODO security
 def query_suggest(request, collection_id, query=""):
   hue_collection = Collection.objects.get(id=collection_id)
@@ -625,7 +406,7 @@ def get_timeline(request):
     collection['facets'] = filter(lambda f: f['widgetType'] == 'histogram-widget', collection['facets'])
     
     response = SolrApi(SOLR_URL.get(), request.user).query2(collection, query)
-    response = augment_solr_response2(response, collection, query)
+    response = augment_solr_response(response, collection, query)
   
     label += ' (%s) ' % response['response']['numFound']