Browse Source

[search] Simplify the UI and first UX

Romain Rigaux 12 years ago
parent
commit
728472e

+ 3 - 1
apps/search/src/search/api.py

@@ -45,7 +45,7 @@ class SolrApi(object):
                 ('wt', 'json'),
                 ('rows', solr_query['rows']),
                 ('start', solr_query['start']),
-                ('facet', solr_query['facets'] == 1 and 'true' or 'false'),
+                ('facet', 'false'), #solr_query['facets'] == 1 and 'true' or 'false'
              )
 
       params += hue_core.get_query()
@@ -56,6 +56,8 @@ class SolrApi(object):
         if fq:
           params += (('fq', fq),)
 
+      # Debug for now
+      print solr_query, params
       response = self._root.get('%(core)s/browse' % solr_query, params)
       return json.loads(response)
     except RestException, e:

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

@@ -46,3 +46,10 @@ class QueryForm(forms.Form):
 
   def _initial_core(self, choices):
     return choices and choices[0][0] or None
+
+
+
+class CoreForm(forms.ModelForm):
+  class Meta:
+    model = Core
+    exclude = ('facets', 'result', 'sorting', 'properties')

+ 30 - 10
apps/search/src/search/models.py

@@ -41,7 +41,7 @@ class DateFacet(object): pass
 
 class Facet(models.Model):
   _ATTRIBUTES = ['properties', 'fields', 'range', 'date']
-  
+
   enabled = models.BooleanField(default=True)
   data = models.TextField()
 
@@ -75,17 +75,17 @@ class Facet(models.Model):
       params += field_facets
 
     if data_dict.get('ranges'):
-      for field_facet in data_dict['ranges']:      
+      for field_facet in data_dict['ranges']:
         range_facets = tuple([
                            ('facet.range', field_facet['field']),
                            ('f.%s.facet.range.start' % field_facet['field'], field_facet['start']),
                            ('f.%s.facet.range.end' % field_facet['field'], field_facet['end']),
                            ('f.%s.facet.range.gap' % field_facet['field'], field_facet['gap']),]
                         )
-        params += range_facets      
- 
+        params += range_facets
+
     if data_dict.get('dates'):
-      for field_facet in data_dict['dates']:      
+      for field_facet in data_dict['dates']:
         range_facets = tuple([
                            ('facet.date', field_facet['field']),
                            ('f.%s.facet.date.start' % field_facet['field'], 'NOW/DAY-305DAYS'),
@@ -93,7 +93,7 @@ class Facet(models.Model):
                            ('f.%s.facet.date.gap' % field_facet['field'], '+%sDAY' % field_facet['gap']),]
                         )
         params += range_facets
- 
+
     return params
 
 
@@ -132,24 +132,44 @@ class Sorting(models.Model):
     if post_data.get('fields'):
       data_dict['fields'] = json.loads(post_data['fields'])
 
-    self.data = json.dumps(data_dict)  
+    self.data = json.dumps(data_dict)
+
+
+
+class CoreManager(models.Manager):
+  def get_or_create(self, name):
+    try:
+      return self.get(name=name)
+    except Core.DoesNotExist:
+      facets = Facet.objects.create(data=json.dumps({
+                   'ranges': [],
+                   'fields': [],
+                   'dates': []
+                }))
+      result = Result.objects.create(data=json.dumps({'template': '{{id}}</br>To customize!<br/>'}))
+      sorting = Sorting.objects.create(data=json.dumps({'fields': []}))
+
+      return Core.objects.create(name=name, label=name, facets=facets, result=result, sorting=sorting)
 
 
 class Core(models.Model):
   enabled = models.BooleanField(default=True)
   name = models.CharField(max_length=40, unique=True, help_text=_t('Name of the Solr collection'))
   label = models.CharField(max_length=100)
+  # solr_address?
   properties = models.TextField(default='[]', verbose_name=_t('Core properties'), help_text=_t('Properties (e.g. facets off, results by pages number)'))
-  
+
   facets = models.ForeignKey(Facet)
   result = models.ForeignKey(Result)
   sorting = models.ForeignKey(Sorting)
 
+  objects = CoreManager()
+
   def get_query(self):
     return self.facets.get_query_params()
 
   def get_absolute_url(self):
-    return reverse('search:admin_core_properties', kwargs={'core': self.name})
+    return reverse('search:admin_core', kwargs={'core': self.name})
 
   @property
   def fields(self):
@@ -163,7 +183,7 @@ class Query(object): pass
 
 
 def temp_fixture_hook():
-  #Core.objects.all().delete()
+  Core.objects.all().delete()
   if not Core.objects.exists():
     facets = Facet.objects.create(data=json.dumps({
                  'ranges': [{"type":"range","field":"price","start":"1","end":"400","gap":"100"}],

+ 1 - 2
apps/search/src/search/templates/admin_core_facets.mako

@@ -114,8 +114,7 @@ ${ commonheader(_('Search'), "search", user) | n,unicode }
 
 
       <div class="form-actions" style="margin-top: 80px">
-        <button type="submit" class="btn btn-primary" id="save-facets">${_('Save Facets')}</button>
-        <a class="btn" href="${ url('search:index') }"><i class="icon-search"></i> ${ _('Back to Search') }</a>
+        <button type="submit" class="btn btn-primary" id="save-facets">${_('Save')}</button>
       </div>
     </form>
   </%def>

+ 9 - 101
apps/search/src/search/templates/admin_core_properties.mako

@@ -29,6 +29,7 @@ ${ commonheader(_('Search'), "search", user) | n,unicode }
       ${ solr_core["status"][hue_core.name]["index"][key] }
     %endif
 </%def>
+
 <%def name="coreProperty(key)">
   %if key in solr_core["status"][hue_core.name]:
       ${ solr_core["status"][hue_core.name][key] }
@@ -39,121 +40,28 @@ ${ commonheader(_('Search'), "search", user) | n,unicode }
   <%def name="title()">
     <h1>${_('Search Admin - ')}${hue_core.label}</h1>
   </%def>
+
   <%def name="navigation()">
     ${ layout.sidebar(hue_core.name, 'properties') }
   </%def>
+
   <%def name="content()">
+  <form method="POST">
     <ul class="nav nav-tabs">
-      <li class="active"><a href="#index" data-toggle="tab">${_('Index properties')}</a></li>
-      <li><a href="#core" data-toggle="tab">${_('Core properties')}</a></li>
+      <li class="active"><a href="#index" data-toggle="tab">${_('Core')}</a></li>
     </ul>
     <div class="tab-content">
       <div class="tab-pane active" id="index">
-        <table class="table">
-          <thead>
-          <tr>
-            <th width="20%">${_('Property')}</th>
-            <th>${_('Value')}</th>
-          </tr>
-          </thead>
-          <tbody>
-          <tr>
-            <td>sizeInBytes</td>
-            <td>${ indexProperty('sizeInBytes') }</td>
-          </tr>
-          <tr>
-            <td>segmentCount</td>
-            <td>${ indexProperty('segmentCount') }</td>
-          </tr>
-          <tr>
-            <td>maxDoc</td>
-            <td>${ indexProperty('maxDoc') }</td>
-          </tr>
-          <tr>
-            <td>lastModified</td>
-            <td>${ indexProperty('lastModified') }</td>
-          </tr>
-          <tr>
-            <td>current</td>
-            <td>${ indexProperty('current') }</td>
-          </tr>
-          <tr>
-            <td>version</td>
-            <td>${ indexProperty('version') }</td>
-          </tr>
-          <tr>
-            <td>directory</td>
-            <td>${ indexProperty('directory') }</td>
-          </tr>
-          <tr>
-            <td>numDocs</td>
-            <td>${ indexProperty('numDocs') }</td>
-          </tr>
-          <tr>
-            <td>hasDeletions</td>
-            <td>${ indexProperty('hasDeletions') }</td>
-          </tr>
-          <tr>
-            <td>size</td>
-            <td>${ indexProperty('size') }</td>
-          </tr>
-          </tbody>
-        </table>
-      </div>
-      <div class="tab-pane" id="core">
-        <table class="table">
-          <thead>
-          <tr>
-            <th width="20%">${_('Property')}</th>
-            <th>${_('Value')}</th>
-          </tr>
-          </thead>
-          <tbody>
-          <tr>
-            <td>uptime</td>
-            <td>${ coreProperty('uptime') }</td>
-          </tr>
-          <tr>
-            <td>name</td>
-            <td>${ coreProperty('name') }</td>
-          </tr>
-          <tr>
-            <td>isDefaultCore</td>
-            <td>${ coreProperty('isDefaultCore') }</td>
-          </tr>
-          <tr>
-            <td>dataDir</td>
-            <td>${ coreProperty('dataDir') }</td>
-          </tr>
-          <tr>
-            <td>instanceDir</td>
-            <td>${ coreProperty('instanceDir') }</td>
-          </tr>
-          <tr>
-            <td>startTime</td>
-            <td>${ coreProperty('startTime') }</td>
-          </tr>
-          <tr>
-            <td>config</td>
-            <td>${ coreProperty('config') }</td>
-          </tr>
-          <tr>
-            <td>schema</td>
-            <td>${ coreProperty('schema') }</td>
-          </tr>
-          </tbody>
-        </table>
+        ${ core_form | n,unicode }
       </div>
     </div>
 
-
     <div class="form-actions">
-      <a class="btn" href="${ url('search:index') }"><i class="icon-search"></i> ${ _('Back to Search') }</a>
+      <button type="submit" class="btn btn-primary" id="save-sorting">${_('Save')}</button>
     </div>
-
+  </form>
   </%def>
+
 </%layout:skeleton>
 
 ${ commonfooter(messages) | n,unicode }
-
-

+ 5 - 4
apps/search/src/search/templates/admin_core_schema.mako

@@ -25,20 +25,21 @@
 ${ commonheader(_('Search'), "search", user) | n,unicode }
 
 <%layout:skeleton>
+
   <%def name="title()">
     <h1>${_('Search Admin - ')}${hue_core.label}</h1>
   </%def>
+
   <%def name="navigation()">
     ${ layout.sidebar(hue_core.name, 'schema') }
   </%def>
+
   <%def name="content()">
     <textarea id="schema">
-    ${ solr_schema.decode('utf-8') }
+      ${ solr_schema.decode('utf-8') }
     </textarea>
-    <div class="form-actions">
-      <a class="btn" href="${ url('search:index') }"><i class="icon-search"></i> ${ _('Back to Search') }</a>
-    </div>
   </%def>
+
 </%layout:skeleton>
 
 

+ 157 - 0
apps/search/src/search/templates/admin_core_solr_properties.mako

@@ -0,0 +1,157 @@
+## 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) | n,unicode }
+
+<%def name="indexProperty(key)">
+  %if key in solr_core["status"][hue_core.name]["index"]:
+      ${ solr_core["status"][hue_core.name]["index"][key] }
+    %endif
+</%def>
+<%def name="coreProperty(key)">
+  %if key in solr_core["status"][hue_core.name]:
+      ${ solr_core["status"][hue_core.name][key] }
+    %endif
+</%def>
+
+<%layout:skeleton>
+
+  <%def name="title()">
+    <h1>${_('Search Admin - ')}${hue_core.label}</h1>
+  </%def>
+
+  <%def name="navigation()">
+    ${ layout.sidebar(hue_core.name, 'index') }
+  </%def>
+
+  <%def name="content()">
+    <ul class="nav nav-tabs">
+      <li class="active"><a href="#index" data-toggle="tab">${_('Index properties')}</a></li>
+      <li><a href="#core" data-toggle="tab">${_('Core properties')}</a></li>
+    </ul>
+    <div class="tab-content">
+      <div class="tab-pane active" id="index">
+        <table class="table">
+          <thead>
+          <tr>
+            <th width="20%">${_('Property')}</th>
+            <th>${_('Value')}</th>
+          </tr>
+          </thead>
+          <tbody>
+          <tr>
+            <td>sizeInBytes</td>
+            <td>${ indexProperty('sizeInBytes') }</td>
+          </tr>
+          <tr>
+            <td>segmentCount</td>
+            <td>${ indexProperty('segmentCount') }</td>
+          </tr>
+          <tr>
+            <td>maxDoc</td>
+            <td>${ indexProperty('maxDoc') }</td>
+          </tr>
+          <tr>
+            <td>lastModified</td>
+            <td>${ indexProperty('lastModified') }</td>
+          </tr>
+          <tr>
+            <td>current</td>
+            <td>${ indexProperty('current') }</td>
+          </tr>
+          <tr>
+            <td>version</td>
+            <td>${ indexProperty('version') }</td>
+          </tr>
+          <tr>
+            <td>directory</td>
+            <td>${ indexProperty('directory') }</td>
+          </tr>
+          <tr>
+            <td>numDocs</td>
+            <td>${ indexProperty('numDocs') }</td>
+          </tr>
+          <tr>
+            <td>hasDeletions</td>
+            <td>${ indexProperty('hasDeletions') }</td>
+          </tr>
+          <tr>
+            <td>size</td>
+            <td>${ indexProperty('size') }</td>
+          </tr>
+          </tbody>
+        </table>
+      </div>
+      <div class="tab-pane" id="core">
+        <table class="table">
+          <thead>
+          <tr>
+            <th width="20%">${_('Property')}</th>
+            <th>${_('Value')}</th>
+          </tr>
+          </thead>
+          <tbody>
+          <tr>
+            <td>uptime</td>
+            <td>${ coreProperty('uptime') }</td>
+          </tr>
+          <tr>
+            <td>name</td>
+            <td>${ coreProperty('name') }</td>
+          </tr>
+          <tr>
+            <td>isDefaultCore</td>
+            <td>${ coreProperty('isDefaultCore') }</td>
+          </tr>
+          <tr>
+            <td>dataDir</td>
+            <td>${ coreProperty('dataDir') }</td>
+          </tr>
+          <tr>
+            <td>instanceDir</td>
+            <td>${ coreProperty('instanceDir') }</td>
+          </tr>
+          <tr>
+            <td>startTime</td>
+            <td>${ coreProperty('startTime') }</td>
+          </tr>
+          <tr>
+            <td>config</td>
+            <td>${ coreProperty('config') }</td>
+          </tr>
+          <tr>
+            <td>schema</td>
+            <td>${ coreProperty('schema') }</td>
+          </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+  </%def>
+</%layout:skeleton>
+
+${ commonfooter(messages) | n,unicode }
+
+

+ 2 - 3
apps/search/src/search/templates/admin_core_sorting.mako

@@ -63,8 +63,7 @@ ${ commonheader(_('Search'), "search", user) | n,unicode }
       </div>
 
       <div class="form-actions" style="margin-top: 80px">
-        <button type="submit" class="btn btn-primary" id="save-sorting">${_('Save Sorting')}</button>
-        <a class="btn" href="${ url('search:index') }"><i class="icon-search"></i> ${ _('Back to Search') }</a>
+        <button type="submit" class="btn btn-primary" id="save-sorting">${_('Save')}</button>
       </div>
     </form>
   </%def>
@@ -148,7 +147,7 @@ ${ commonheader(_('Search'), "search", user) | n,unicode }
           $("#save-sorting").button('reset');
         }
       });
-    };    
+    };
   };
 
   var viewModel = new ViewModel();

+ 4 - 5
apps/search/src/search/templates/admin_core_template.mako

@@ -44,13 +44,12 @@ ${ commonheader(_('Search'), "search", user) | n,unicode }
 
 <%layout:skeleton>
   <%def name="title()">
-    <h1>${_('Search Admin - ')}${hue_core.label}</h1>
+    <h1>${ _('Template Editor ') } : ${ hue_core.name }</h1>
   </%def>
   <%def name="navigation()">
     ${ layout.sidebar(hue_core.name, 'template') }
   </%def>
   <%def name="content()">
-
     <ul class="nav nav-tabs">
       <li class="active"><a href="#visual" data-toggle="tab">${_('Visual editor')}</a></li>
       <li><a href="#source" data-toggle="tab">${_('Source')}</a></li>
@@ -74,7 +73,7 @@ ${ commonheader(_('Search'), "search", user) | n,unicode }
             <div class="well available-fields">
               <h4>${_('Available Fields')}</h4>
               <ul data-bind="foreach: fields">
-                <li data-bind="text: $data, click: $root.addField"></li>
+                <li data-bind="text: $data, click: $root.addField" title="${ _('Click to append to the template') }"></li>
               </ul>
             </div>
           </div>
@@ -105,8 +104,8 @@ ${ commonheader(_('Search'), "search", user) | n,unicode }
     </div>
 
     <div class="form-actions">
-      <a class="btn btn-primary" id="save-template">${_('Save Template')}</a>
-      <a class="btn" href="${ url('search:index') }"><i class="icon-search"></i> ${ _('Back to Search') }</a>
+      <a class="btn" id="save-template">${_('Save')}</a>
+      <a class="btn btn-primary" id="save-template">${_('Save and next')}</a>
     </div>
 
     <div id="load-template-modal" class="modal hide fade">

+ 21 - 5
apps/search/src/search/templates/index.mako

@@ -26,7 +26,7 @@ ${ commonheader(_('Search'), "search", user, "40px") | n,unicode }
 <div class="search-bar">
   % if user.is_superuser:
     <div class="pull-right" style="margin-top: 4px">
-      <a class="change-settings" href="#"><i class="icon-edit"></i> ${ _('Change settings for this Core') }</a>
+      <a class="change-settings btn" href="#"><i class="icon-edit"></i> ${ _('Customize this Index') }</a>
     </div>
   % endif
   <form class="form-search" style="margin: 0">
@@ -53,10 +53,17 @@ ${ commonheader(_('Search'), "search", user, "40px") | n,unicode }
 
 <div class="container-fluid">
   <div class="row-fluid">
+    % if error:
+    <div class="span12">
+      <div class="alert">
+        ${ error['message'] }
+      </div>
+    </div>
+    %else:
     % if response and response['response']['docs'] and len(response['response']['docs']) > 0 and solr_query['facets'] == 1:
     <div class="span2">
       <ul class="facet-list">
-        % if response and response['facet_counts']:
+        % if response and response.get('facet_counts'):
           % if response['facet_counts']['facet_fields']:
             % for cat in response['facet_counts']['facet_fields']:
                 % if response['facet_counts']['facet_fields'][cat]:
@@ -158,10 +165,18 @@ ${ commonheader(_('Search'), "search", user, "40px") | n,unicode }
             next = int(solr_query["start"]) + int(solr_query["rows"])
           %>
           % if int(solr_query["start"]) > 0:
-            <li><a title="${_('Beginning of List')}" href="?query=${solr_query["q"]}&fq=${solr_query["fq"]}&sort=${solr_query["sort"]}&rows=${solr_query["rows"]}&start=${beginning}">&larr; ${_('Beginning of List')}</a></li>
-            <li><a title="Previous Page" href="?query=${solr_query["q"]}&fq=${solr_query["fq"]}&sort=${solr_query["sort"]}&rows=${solr_query["rows"]}&start=${previous}">${_('Previous Page')}</a></li>
+            <li>
+              <a title="${_('Beginning of List')}" href="?query=${solr_query["q"]}&fq=${solr_query["fq"]}&sort=${solr_query["sort"]}&rows=${solr_query["rows"]}&start=${beginning}">&larr; ${_('Beginning of List')}</a>
+            </li>
+            <li>
+              <a title="Previous Page" href="?query=${solr_query["q"]}&fq=${solr_query["fq"]}&sort=${solr_query["sort"]}&rows=${solr_query["rows"]}&start=${previous}">${_('Previous Page')}</a>
+            </li>
+          % endif
+          % if end_record < int(response["response"]["numFound"]):
+            <li>
+              <a title="Next page" href="?query=${solr_query["q"]}&fq=${solr_query["fq"]}&sort=${solr_query["sort"]}&rows=${solr_query["rows"]}&start=${next}">${_('Next Page')}</a>
+            </li>
           % endif
-          <li><a title="Next page" href="?query=${solr_query["q"]}&fq=${solr_query["fq"]}&sort=${solr_query["sort"]}&rows=${solr_query["rows"]}&start=${next}">${_('Next Page')}</a></li>
         </ul>
       </div>
     </div>
@@ -173,6 +188,7 @@ ${ commonheader(_('Search'), "search", user, "40px") | n,unicode }
     </div>
     % endif
   </div>
+  % endif
 </div>
 
 <div class="hide">

+ 32 - 16
apps/search/src/search/templates/layout.mako

@@ -24,14 +24,6 @@
   <link rel="stylesheet" href="/search/static/css/admin.css">
 
   <div class="container-fluid">
-    <div class="pull-right" style="margin-top: 20px">
-      <span class="muted">${ _('Change settings for') }</span>
-      <select id="change-core" style="margin-bottom: 0;display: inline">
-          % for c in hue_cores:
-            <option value="${ c.get_absolute_url() }"> ${ c.label } (${ c.name })</option>
-          % endfor
-      </select>
-    </div>
     %if hasattr(caller, "title"):
       ${caller.title()}
     %else:
@@ -69,22 +61,46 @@
 <%def name="sidebar(core, section='')">
   <div class="well sidebar-nav" style="min-height: 250px">
     <ul class="nav nav-list">
-      <li class="nav-header">${_('Core')}</li>
+
+    <li class="nav-header">${_('Core')}</li>
+    <li>
+      <div>
+      ##<span class="muted">${ _('Change settings for') }</span>
+      ##<select id="change-core" style="margin-bottom: 0;display: inline">
+      ##  % for c in hue_cores:
+      ##    <option value="${ c.get_absolute_url() }"> ${ c.label } (${ c.name })</option>
+      ##  % endfor
+      ##</select>
+      </div>
+    </li>
       <li class="${ utils.is_selected(section, 'properties') }">
         <a href="${ url('search:admin_core_properties', core=core) }">${_('Properties')}</a>
       </li>
-      <li class="${ utils.is_selected(section, 'schema') }">
-        <a href="${ url('search:admin_core_schema', core=core) }">${_('Schema')}</a>
-      </li>
-      <li class="nav-header">${_('Results')}</li>
+
+      <li class="nav-header">${_('Template')}</li>
       <li class="${ utils.is_selected(section, 'template') }">
-        <a href="${ url('search:admin_core_template', core=core) }">${_('Template')}</a>
+        <a href="${ url('search:admin_core_template', core=core) }">${_('1. Snippet')}</a>
       </li>
       <li class="${ utils.is_selected(section, 'facets') }">
-        <a href="${ url('search:admin_core_facets', core=core) }">${_('Facets')}</a>
+        <a href="${ url('search:admin_core_facets', core=core) }">${_('2. Facets')}</a>
       </li>
       <li class="${ utils.is_selected(section, 'sorting') }">
-        <a href="${ url('search:admin_core_sorting', core=core) }">${_('Sorting')}</a>
+        <a href="${ url('search:admin_core_sorting', core=core) }">${_('3. Sorting')}</a>
+      </li>
+      <li class="${ utils.is_selected(section, 'autocomplete') }">
+        <a href="${ url('search:admin_core_sorting', core=core) }">${_('4. Auto-complete')}</a>
+      </li>
+      <li class="nav-header">${_('Search')}</li>
+      <li>
+        <a href="${ url('search:index') }"><i class="icon-share-alt"></i> ${ _('Query UI') }</a>
+      </li>
+
+      <li class="nav-header">${_('Solr')}</li>
+      <li class="${ utils.is_selected(section, 'index') }">
+        <a href="${ url('search:admin_core_solr_properties', core=core) }">${_('Index')}</a>
+      </li>
+      <li class="${ utils.is_selected(section, 'schema') }">
+        <a href="${ url('search:admin_core_schema', core=core) }">${_('Schema')}</a>
       </li>
     </ul>
   </div>

+ 2 - 0
apps/search/src/search/urls.py

@@ -22,7 +22,9 @@ urlpatterns = patterns('search.views',
   url(r'^query$', 'index', name='query'),
   url(r'^admin$', 'admin', name='admin'),
   url(r'^admin/cores$', 'admin', name='admin_cores'),
+  url(r'^admin/core/(?P<core>\w+)$', 'admin_core_template', name='admin_core'),
   url(r'^admin/core/(?P<core>\w+)/properties$', 'admin_core_properties', name='admin_core_properties'),
+  url(r'^admin/core/(?P<core>\w+)/solr_properties$', 'admin_core_solr_properties', name='admin_core_solr_properties'),
   url(r'^admin/core/(?P<core>\w+)/schema$', 'admin_core_schema', name='admin_core_schema'),
   url(r'^admin/core/(?P<core>\w+)/template$', 'admin_core_template', name='admin_core_template'),
   url(r'^admin/core/(?P<core>\w+)/facets$', 'admin_core_facets', name='admin_core_facets'),

+ 40 - 4
apps/search/src/search/views.py

@@ -22,15 +22,17 @@ except ImportError:
 
 import logging
 
+from django.core.urlresolvers import reverse
 from django.http import HttpResponse
 from django.utils.translation import ugettext as _
+from django.shortcuts import redirect
 
 from desktop.lib.django_util import render
 
 from search.api import SolrApi
 from search.conf import SOLR_URL
 from search.decorators import allow_admin_only
-from search.forms import QueryForm
+from search.forms import QueryForm, CoreForm
 from search.models import Core, temp_fixture_hook
 
 
@@ -38,13 +40,19 @@ LOG = logging.getLogger(__name__)
 
 
 def index(request):
-  temp_fixture_hook()
+  #Core.objects.all().delete()
+  ##temp_fixture_hook()
 
   cores = SolrApi(SOLR_URL.get()).cores()
   hue_cores = Core.objects.all()
 
+  if not hue_cores:
+    for core in cores['status']:
+      Core.objects.get_or_create(name=core)
+
   search_form = QueryForm(request.GET)
   response = {}
+  error = {}
   solr_query = {}
 
   if search_form.is_valid():
@@ -57,13 +65,17 @@ def index(request):
     solr_query['start'] = search_form.cleaned_data['start'] or 0
     solr_query['facets'] = search_form.cleaned_data['facets'] or 1
 
-    hue_core = Core.objects.get(name=core)
+    hue_core = Core.objects.get_or_create(name=core)
 
-    response = SolrApi(SOLR_URL.get()).query(solr_query, hue_core)
+    try:
+      response = SolrApi(SOLR_URL.get()).query(solr_query, hue_core)
+    except Exception, e:
+      error['message'] = unicode(str(e), "utf8")
 
   return render('index.mako', request, {
     'search_form': search_form,
     'response': response,
+    'error': error,
     'solr_query': solr_query,
     'hue_core': hue_core,
     'hue_cores': hue_cores,
@@ -90,10 +102,34 @@ def admin_core_properties(request, core):
   hue_core = Core.objects.get(name=core)
   hue_cores = Core.objects.all()
 
+  if request.method == 'POST':
+    core_form = CoreForm(request.POST, instance=hue_core)
+    if core_form.is_valid():
+      hue_core = core_form.save()
+      return redirect(reverse('search:admin_core_properties', kwargs={'core': hue_core.name}))
+    else:
+      request.error(_('Errors on the form: %s') % core_form.errors)
+  else:
+    core_form = CoreForm(instance=hue_core)
+
   return render('admin_core_properties.mako', request, {
     'solr_core': solr_core,
     'hue_core': hue_core,
     'hue_cores': hue_cores,
+    'core_form': core_form,
+  })
+
+
+@allow_admin_only
+def admin_core_solr_properties(request, core):
+  solr_core = SolrApi(SOLR_URL.get()).core(core)
+  hue_core = Core.objects.get(name=core)
+  hue_cores = Core.objects.all()
+
+  return render('admin_core_solr_properties.mako', request, {
+    'solr_core': solr_core,
+    'hue_core': hue_core,
+    'hue_cores': hue_cores,
   })