mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-03 07:55:36 +00:00
add search results highlight
This commit is contained in:
@@ -13,6 +13,11 @@ try:
|
||||
except ImportError:
|
||||
BUSINESS_MODE = False
|
||||
|
||||
try:
|
||||
from settings import ENABLE_FILE_SEARCH
|
||||
except ImportError:
|
||||
ENABLE_FILE_SEARCH = False
|
||||
|
||||
def base(request):
|
||||
"""
|
||||
Add seahub base configure to the context.
|
||||
@@ -37,5 +42,6 @@ def base(request):
|
||||
'site_name': SITE_NAME,
|
||||
'enable_signup': ENABLE_SIGNUP,
|
||||
'max_file_name': MAX_FILE_NAME,
|
||||
'enable_file_search': ENABLE_FILE_SEARCH,
|
||||
}
|
||||
|
||||
|
@@ -182,3 +182,16 @@ class DirFilesLastModifiedInfo(models.Model):
|
||||
|
||||
class Meta:
|
||||
unique_together = ('repo_id', 'parent_dir_hash')
|
||||
|
||||
class FileLastModifiedInfo(models.Model):
|
||||
repo_id = models.CharField(max_length=36, db_index=True)
|
||||
file_id = models.CharField(max_length=40)
|
||||
|
||||
file_path = models.TextField()
|
||||
file_path_hash = models.CharField(max_length=12)
|
||||
|
||||
last_modified = models.BigIntegerField()
|
||||
email = models.EmailField()
|
||||
|
||||
class Meta:
|
||||
unique_together = ('repo_id', 'file_path_hash')
|
@@ -1971,6 +1971,41 @@ textarea:-moz-placeholder {/* for FF */
|
||||
background:#f7f7f8;
|
||||
border-radius:2px;
|
||||
}
|
||||
|
||||
#search-results {
|
||||
padding-top:15px;
|
||||
}
|
||||
|
||||
#search-results a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#search-results b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.search-results-item {
|
||||
margin-top: 20px;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.search-results-item .file-icon {
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.search-results-item .title {
|
||||
margin: 0 0 0 40px;
|
||||
}
|
||||
|
||||
.search-results-item .title a,
|
||||
.search-results-item .title img,
|
||||
.search-results-item .title span
|
||||
{
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.search-results-item .content {
|
||||
clear: left;
|
||||
margin: 0 0 0 40px;
|
||||
}
|
@@ -87,7 +87,7 @@
|
||||
</a>
|
||||
{% block nav %}{% endblock %}
|
||||
|
||||
{% if request.user.is_authenticated %}
|
||||
{% if enable_file_search and request.user.is_authenticated %}
|
||||
<form id="top-search-form" method="get" action="{% url 'search' %}" class="search-form fright">
|
||||
<input class="search-input" name="q" placeholder="{% trans 'Search Files' %}" value="{{ keyword }}" />
|
||||
<input type="submit" value="" class="search-submit" />
|
||||
|
@@ -16,26 +16,39 @@
|
||||
<p>{% trans 'No result found' %}</p>
|
||||
{% else %}
|
||||
<p class="tip">{% blocktrans count counter=total %}{{ total }} result{% plural %}{{ total }} results{% endblocktrans%}</p>
|
||||
<table>
|
||||
<tr>
|
||||
<th width="5%"></th>
|
||||
<th width="45%">{% trans 'Name' %}</th>
|
||||
<th width="22%">{% trans 'Library' %}</th>
|
||||
<th width="28%">{% trans 'Owner' %}</th>
|
||||
</tr>
|
||||
<ul id="search-results-list">
|
||||
{% for file in results %}
|
||||
<tr>
|
||||
<td><img src="{{ MEDIA_URL }}img/file/{{ file.name|file_icon_filter }}" alt="{% trans "File"%}" /></td>
|
||||
<td><a href="{% url 'repo_view_file' repo_id=file.repo.id %}?p={{ file.fullpath|urlencode }}" target="_blank">{{ file.name }}</a></td>
|
||||
<td><a href="{% url 'repo' repo_id=file.repo.id %}" target="_blank">{{ file.repo.name }}</a></td>
|
||||
<td>
|
||||
{% avatar file.repo.owner 20 %}
|
||||
<a class="name" href="{% url 'profile.views.user_profile' file.repo.owner %}" target="_blank">{{ file.repo.owner|email2nickname }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<li class="search-results-item">
|
||||
<img class="file-icon" src="{{ MEDIA_URL }}img/file/{{ file.name|file_icon_filter }}" alt="{% trans "File"%}" />
|
||||
<div class="title">
|
||||
<a href="{% url 'repo' repo_id=file.repo.id %}" target="_blank">{{ file.repo.name }}</a>
|
||||
<span>–</span>
|
||||
<a class="filename" href="{% url 'repo_view_file' repo_id=file.repo.id %}?p={{ file.fullpath|urlencode }}" target="_blank" title="{{ file.fullpath|slice:'1:'}}" >
|
||||
{% if file.name_highlight %}
|
||||
{{ file.name_highlight|safe }}
|
||||
{% else %}
|
||||
{{ file.name }}
|
||||
{% endif %}
|
||||
</a>
|
||||
<p>
|
||||
{% if file.last_modified_by %}
|
||||
{% avatar file.last_modified_by 20 %}
|
||||
<a class="name" href="{% url 'profile.views.user_profile' file.last_modified_by %}">{{ file.last_modified_by|email2nickname }}</a>
|
||||
{% endif %}
|
||||
{% if file.last_modified %}
|
||||
{{ file.last_modified|translate_seahub_time }}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
{% if file.content_highlight %}
|
||||
<div class="content">
|
||||
{{ file.content_highlight|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% if total > 25 %}
|
||||
</ul>
|
||||
{% if total > per_page %}
|
||||
<div id="paginator">
|
||||
{% if current_page != 1 %}
|
||||
<a href="?q={{ keyword|urlencode }}&page={{ prev_page }}&per_page={{ per_page }}">{% trans "Previous"%}</a>
|
||||
|
6
urls.py
6
urls.py
@@ -103,7 +103,6 @@ urlpatterns = patterns('',
|
||||
url(r'^sys/orgadmin/$', sys_org_admin, name='sys_org_admin'),
|
||||
url(r'^sys/groupadmin/$', sys_group_admin, name='sys_group_admin'),
|
||||
|
||||
url(r'^search/$', search, name='search'),
|
||||
)
|
||||
|
||||
if settings.SERVE_STATIC:
|
||||
@@ -128,3 +127,8 @@ else:
|
||||
url(r'^pubinfo/groups/$', pubgrp, name='pubgrp'),
|
||||
url(r'^pubinfo/users/$', pubuser, name='pubuser'),
|
||||
)
|
||||
|
||||
if getattr(settings, 'ENABLE_FILE_SEARCH', False):
|
||||
urlpatterns += patterns('',
|
||||
url(r'^search/$', search, name='search'),
|
||||
)
|
@@ -15,7 +15,7 @@ from django.template import RequestContext
|
||||
from django.utils.hashcompat import sha_constructor, md5_constructor
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from base.models import FileContributors, UserStarredFiles, DirFilesLastModifiedInfo
|
||||
from base.models import FileContributors, UserStarredFiles, DirFilesLastModifiedInfo, FileLastModifiedInfo
|
||||
|
||||
from htmldiff import HtmlDiff
|
||||
|
||||
@@ -406,6 +406,54 @@ def check_and_get_org_by_group(group_id, user):
|
||||
|
||||
return org, base_template
|
||||
|
||||
def calc_file_last_modified(repo_id, file_path, file_path_hash, file_id):
|
||||
try:
|
||||
# get the lastest one file revision
|
||||
commits = seafserv_threaded_rpc.list_file_revisions(repo_id, file_path, 1, -1)
|
||||
except SearpcError, e:
|
||||
return '', 0
|
||||
|
||||
if not commits:
|
||||
return '', 0
|
||||
|
||||
email, last_modified = commits[0].creator_name, commits[0].ctime
|
||||
|
||||
info = FileLastModifiedInfo(repo_id=repo_id,
|
||||
file_path=file_path,
|
||||
file_path_hash=file_path_hash,
|
||||
file_id=file_id,
|
||||
last_modified=last_modified,
|
||||
email=email)
|
||||
try:
|
||||
info.save()
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
return email, last_modified
|
||||
|
||||
def get_file_last_modified(repo_id, file_path):
|
||||
email = ''
|
||||
last_modified = 0
|
||||
file_path_hash = calc_file_path_hash(file_path)
|
||||
file_id = seafserv_threaded_rpc.get_file_id_by_path(repo_id, file_path)
|
||||
try:
|
||||
fc = FileLastModifiedInfo.objects.get(repo_id=repo_id,
|
||||
file_path_hash=file_path_hash)
|
||||
except FileLastModifiedInfo.DoesNotExist:
|
||||
# has no cache yet
|
||||
user, last_modified = calc_file_last_modified(repo_id, file_path, file_path_hash, file_id)
|
||||
else:
|
||||
# cache found
|
||||
if fc.file_id != file_id:
|
||||
# but cache is outdated
|
||||
fc.delete()
|
||||
user, last_modified = calc_file_last_modified(repo_id, file_path, file_path_hash, file_id)
|
||||
else:
|
||||
# cache is valid
|
||||
user, last_modified = fc.email, fc.last_modified
|
||||
|
||||
return user, last_modified
|
||||
|
||||
def get_file_contributors_from_revisions(repo_id, file_path):
|
||||
"""Inspect the file history and get a list of users who have modified the
|
||||
it.
|
||||
@@ -413,7 +461,7 @@ def get_file_contributors_from_revisions(repo_id, file_path):
|
||||
"""
|
||||
commits = []
|
||||
try:
|
||||
commits = seafserv_threaded_rpc.list_file_revisions(repo_id, file_path, -1)
|
||||
commits = seafserv_threaded_rpc.list_file_revisions(repo_id, file_path, -1, -1)
|
||||
except SearpcError, e:
|
||||
return [], 0, ''
|
||||
|
||||
@@ -770,12 +818,11 @@ def is_textual_file(file_type):
|
||||
else:
|
||||
return False
|
||||
|
||||
if getattr(settings, 'ENABLE_FILE_SEARCH', False):
|
||||
from seafes import es_get_conn, es_search
|
||||
|
||||
from seafes import es_get_conn, es_search
|
||||
|
||||
conn = es_get_conn()
|
||||
|
||||
def search_file_by_name(request, keyword, start, size):
|
||||
conn = es_get_conn()
|
||||
def search_file_by_name(request, keyword, start, size):
|
||||
owned_repos, shared_repos, groups_repos, pub_repo_list = get_user_repos(request.user)
|
||||
|
||||
# unify the repo.owner property
|
||||
@@ -812,6 +859,17 @@ def search_file_by_name(request, keyword, start, size):
|
||||
repo_id_map.update(pubrepo_id_map)
|
||||
|
||||
for f in files_found:
|
||||
f['repo'] = repo_id_map[f['repo_id'].encode('UTF-8')]
|
||||
repo = repo_id_map.get(f['repo_id'].encode('UTF-8'), None)
|
||||
if repo:
|
||||
f['repo'] = repo
|
||||
f['exists'] = True
|
||||
f['last_modified_by'], f['last_modified'] = get_file_last_modified(f['repo_id'], f['fullpath'])
|
||||
else:
|
||||
f['exists'] = False
|
||||
|
||||
files_found = filter(lambda f: f['exists'], files_found)
|
||||
|
||||
return files_found, total
|
||||
else:
|
||||
def search_file_by_name(*args):
|
||||
pass
|
||||
|
Reference in New Issue
Block a user