mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-30 21:50:59 +00:00
Rewrite get_user_starred_files, improved performance
This commit is contained in:
parent
8fa3162a72
commit
b84cd16bb7
@ -22,14 +22,15 @@ from authentication import TokenAuthentication
|
||||
from permissions import IsRepoWritable, IsRepoAccessible, IsRepoOwner
|
||||
from serializers import AuthTokenSerializer
|
||||
from seahub.base.accounts import User
|
||||
from seahub.base.models import FileDiscuss
|
||||
from seahub.base.models import FileDiscuss, UserStarredFiles
|
||||
from seahub.share.models import FileShare
|
||||
from seahub.views import access_to_repo, validate_owner, is_registered_user, events, group_events_data, get_diff
|
||||
from seahub.utils import gen_file_get_url, gen_token, gen_file_upload_url, \
|
||||
check_filename_with_rename, get_starred_files, get_ccnetapplet_root, \
|
||||
check_filename_with_rename, get_ccnetapplet_root, \
|
||||
get_dir_files_last_modified, get_user_events, EMPTY_SHA1, \
|
||||
get_ccnet_server_addr_port, star_file, unstar_file, string2list, \
|
||||
get_ccnet_server_addr_port, string2list, \
|
||||
gen_block_get_url
|
||||
from seahub.utils.star import star_file, unstar_file
|
||||
try:
|
||||
from seahub.settings import CLOUD_MODE
|
||||
except ImportError:
|
||||
@ -647,7 +648,8 @@ def append_starred_files(array, files):
|
||||
|
||||
def api_starred_files(request):
|
||||
starred_files = []
|
||||
personal_files = get_starred_files(request.user.username, -1)
|
||||
personal_files = UserStarredFiles.objects.get_starred_files_by_username(
|
||||
request.user.username)
|
||||
append_starred_files (starred_files, personal_files)
|
||||
return Response(starred_files)
|
||||
|
||||
|
@ -1,16 +1,22 @@
|
||||
import datetime
|
||||
import logging
|
||||
import re
|
||||
from django.db import models
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from seaserv import get_emailusers
|
||||
from pysearpc import SearpcError
|
||||
from seaserv import seafile_api, get_emailusers
|
||||
|
||||
from seahub.shortcuts import get_first_object_or_none
|
||||
from seahub.base.templatetags.seahub_tags import at_pattern
|
||||
from seahub.group.models import GroupMessage
|
||||
from seahub.notifications.models import UserNotification
|
||||
from seahub.profile.models import Profile
|
||||
from seahub.utils import get_files_last_modified
|
||||
|
||||
# Get an instance of a logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class UuidObjidMap(models.Model):
|
||||
"""
|
||||
@ -49,119 +55,112 @@ class FileContributors(models.Model):
|
||||
# email addresses seperated by comma
|
||||
emails = models.TextField()
|
||||
|
||||
class InnerPubMsg(models.Model):
|
||||
"""
|
||||
Model used for leave message on inner pub page.
|
||||
"""
|
||||
from_email = models.EmailField()
|
||||
message = models.CharField(max_length=500)
|
||||
timestamp = models.DateTimeField(default=datetime.datetime.now)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-timestamp']
|
||||
|
||||
class InnerPubMsgReply(models.Model):
|
||||
reply_to = models.ForeignKey(InnerPubMsg)
|
||||
from_email = models.EmailField()
|
||||
message = models.CharField(max_length=150)
|
||||
timestamp = models.DateTimeField(default=datetime.datetime.now)
|
||||
class StarredFile(object):
|
||||
def format_path(self):
|
||||
if self.path == "/":
|
||||
return self.path
|
||||
|
||||
# @receiver(post_save, sender=InnerPubMsgReply)
|
||||
def msgreply_save_handler(sender, instance, **kwargs):
|
||||
"""
|
||||
Handle sending notification to '@<user>' when reply messages.
|
||||
"""
|
||||
from_email = instance.from_email
|
||||
reply_msg = instance.message
|
||||
innerpub_msg = instance.reply_to
|
||||
to_user = ''
|
||||
# strip leading slash
|
||||
path = self.path[1:]
|
||||
if path[-1:] == '/':
|
||||
path = path[:-1]
|
||||
return path.replace('/', ' / ')
|
||||
|
||||
def __init__(self, org_id, repo, file_id, path, is_dir, size):
|
||||
# always 0 for non-org repo
|
||||
self.org_id = org_id
|
||||
self.repo = repo
|
||||
self.file_id = file_id
|
||||
self.path = path
|
||||
self.formatted_path = self.format_path()
|
||||
self.is_dir = is_dir
|
||||
self.size = size
|
||||
self.last_modified = None
|
||||
if not is_dir:
|
||||
self.name = path.split('/')[-1]
|
||||
|
||||
m = re.match(at_pattern, reply_msg)
|
||||
if m:
|
||||
nickname_or_emailprefix = m.group()[1:]
|
||||
for member in get_emailusers(-1, -1):
|
||||
# For every user, get his username and nickname if
|
||||
# it exists, check whether match.
|
||||
username = member.email
|
||||
if username == from_email:
|
||||
class UserStarredFilesManager(models.Manager):
|
||||
def get_starred_files_by_username(self, username):
|
||||
"""Get a user's starred files.
|
||||
|
||||
Arguments:
|
||||
- `self`:
|
||||
- `username`:
|
||||
"""
|
||||
starred_files = super(UserStarredFilesManager, self).filter(
|
||||
email=username, org_id=-1)
|
||||
|
||||
ret = []
|
||||
repo_cache = {}
|
||||
for sfile in starred_files:
|
||||
# repo still exists?
|
||||
if repo_cache.has_key(sfile.repo_id):
|
||||
repo = repo_cache[sfile.repo_id]
|
||||
else:
|
||||
try:
|
||||
repo = seafile_api.get_repo(sfile.repo_id)
|
||||
except SearpcError:
|
||||
continue
|
||||
if repo is not None:
|
||||
repo_cache[sfile.repo_id] = repo
|
||||
else:
|
||||
sfile.delete()
|
||||
continue
|
||||
|
||||
# file still exists?
|
||||
file_id = ''
|
||||
size = -1
|
||||
if sfile.path != "/":
|
||||
try:
|
||||
file_id = seafile_api.get_file_id_by_path(sfile.repo_id,
|
||||
sfile.path)
|
||||
# size = seafile_api.get_file_size(file_id)
|
||||
except SearpcError:
|
||||
continue
|
||||
if not file_id:
|
||||
sfile.delete()
|
||||
continue
|
||||
|
||||
f = StarredFile(sfile.org_id, repo, file_id, sfile.path,
|
||||
sfile.is_dir, 0) # TODO: remove ``size`` from StarredFile
|
||||
ret.append(f)
|
||||
|
||||
'''Calculate files last modification time'''
|
||||
files_list = []
|
||||
for sfile in ret:
|
||||
if sfile.is_dir:
|
||||
continue
|
||||
|
||||
p = get_first_object_or_none(
|
||||
Profile.objects.filter(user=username))
|
||||
nickname = p.nickname if p else ''
|
||||
if nickname == nickname_or_emailprefix or \
|
||||
username.split('@')[0] == nickname_or_emailprefix:
|
||||
to_user = username
|
||||
break
|
||||
ele = (sfile.repo.id, sfile.path, sfile.file_id)
|
||||
files_list.append(ele)
|
||||
|
||||
if to_user:
|
||||
# Send notification to the user if he replies someone else'
|
||||
# message.
|
||||
try:
|
||||
UserNotification.objects.get(to_user=to_user,
|
||||
msg_type='innerpubmsg_reply',
|
||||
detail=innerpub_msg.id)
|
||||
except UserNotification.DoesNotExist:
|
||||
n = UserNotification(to_user=to_user,
|
||||
msg_type='innerpubmsg_reply',
|
||||
detail=innerpub_msg.id)
|
||||
n.save()
|
||||
|
||||
# @receiver(post_save, sender=InnerPubMsg)
|
||||
def innerpub_msg_added_cb(sender, instance, **kwargs):
|
||||
from_email = instance.from_email
|
||||
files_dict_with_last_modified = get_files_last_modified(files_list)
|
||||
|
||||
users = get_emailusers(-1, -1)
|
||||
for u in users:
|
||||
if u.email == from_email:
|
||||
continue
|
||||
try:
|
||||
UserNotification.objects.get(to_user=u.email,
|
||||
msg_type='innerpub_msg')
|
||||
except UserNotification.DoesNotExist:
|
||||
n = UserNotification(to_user=u.email, msg_type='innerpub_msg',
|
||||
detail='')
|
||||
n.save()
|
||||
for sfile in ret:
|
||||
key = "%s|%s|%s" % (sfile.repo.id, sfile.path, sfile.file_id)
|
||||
if files_dict_with_last_modified.has_key(key):
|
||||
sfile.last_modified = files_dict_with_last_modified[key]
|
||||
else:
|
||||
# Should never reach here
|
||||
pass
|
||||
|
||||
# @receiver(post_save, sender=InnerPubMsgReply)
|
||||
def innerpubmsg_reply_added_cb(sender, instance, **kwargs):
|
||||
innerpub_msg = instance.reply_to
|
||||
from_email = instance.from_email
|
||||
msg_id = innerpub_msg.id
|
||||
|
||||
if from_email == innerpub_msg.from_email:
|
||||
# No need to send notification when reply own message.
|
||||
return
|
||||
ret.sort(lambda x, y: cmp(y.last_modified, x.last_modified))
|
||||
|
||||
try:
|
||||
innerpub_msg = InnerPubMsg.objects.get(id=msg_id)
|
||||
except InnerPubMsg.DoesNotExist:
|
||||
pass
|
||||
|
||||
try:
|
||||
UserNotification.objects.get(to_user=innerpub_msg.from_email,
|
||||
msg_type='innerpubmsg_reply',
|
||||
detail=msg_id)
|
||||
except UserNotification.DoesNotExist:
|
||||
n = UserNotification(to_user=innerpub_msg.from_email,
|
||||
msg_type='innerpubmsg_reply',
|
||||
detail=msg_id)
|
||||
n.save()
|
||||
return ret
|
||||
|
||||
class UserStarredFiles(models.Model):
|
||||
"""Starred files are marked by users to get quick access to it on user
|
||||
home page.
|
||||
|
||||
"""
|
||||
|
||||
email = models.EmailField()
|
||||
org_id = models.IntegerField()
|
||||
repo_id = models.CharField(max_length=36, db_index=True)
|
||||
|
||||
path = models.TextField()
|
||||
is_dir = models.BooleanField()
|
||||
|
||||
objects = UserStarredFilesManager()
|
||||
|
||||
class DirFilesLastModifiedInfo(models.Model):
|
||||
'''Cache the results of the calculation of last modified time of all the
|
||||
files under a directory <parent_dir> in repo <repo_id>.
|
||||
@ -188,10 +187,111 @@ class FileLastModifiedInfo(models.Model):
|
||||
file_id = models.CharField(max_length=40)
|
||||
|
||||
file_path = models.TextField()
|
||||
file_path_hash = models.CharField(max_length=12)
|
||||
file_path_hash = models.CharField(max_length=12, db_index=True)
|
||||
|
||||
last_modified = models.BigIntegerField()
|
||||
email = models.EmailField()
|
||||
|
||||
class Meta:
|
||||
unique_together = ('repo_id', 'file_path_hash')
|
||||
|
||||
###### Deprecated
|
||||
class InnerPubMsg(models.Model):
|
||||
"""
|
||||
Model used for leave message on inner pub page.
|
||||
"""
|
||||
from_email = models.EmailField()
|
||||
message = models.CharField(max_length=500)
|
||||
timestamp = models.DateTimeField(default=datetime.datetime.now)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-timestamp']
|
||||
|
||||
class InnerPubMsgReply(models.Model):
|
||||
reply_to = models.ForeignKey(InnerPubMsg)
|
||||
from_email = models.EmailField()
|
||||
message = models.CharField(max_length=150)
|
||||
timestamp = models.DateTimeField(default=datetime.datetime.now)
|
||||
|
||||
# # @receiver(post_save, sender=InnerPubMsgReply)
|
||||
# def msgreply_save_handler(sender, instance, **kwargs):
|
||||
# """
|
||||
# Handle sending notification to '@<user>' when reply messages.
|
||||
# """
|
||||
# from_email = instance.from_email
|
||||
# reply_msg = instance.message
|
||||
# innerpub_msg = instance.reply_to
|
||||
# to_user = ''
|
||||
|
||||
|
||||
# m = re.match(at_pattern, reply_msg)
|
||||
# if m:
|
||||
# nickname_or_emailprefix = m.group()[1:]
|
||||
# for member in get_emailusers(-1, -1):
|
||||
# # For every user, get his username and nickname if
|
||||
# # it exists, check whether match.
|
||||
# username = member.email
|
||||
# if username == from_email:
|
||||
# continue
|
||||
|
||||
# p = get_first_object_or_none(
|
||||
# Profile.objects.filter(user=username))
|
||||
# nickname = p.nickname if p else ''
|
||||
# if nickname == nickname_or_emailprefix or \
|
||||
# username.split('@')[0] == nickname_or_emailprefix:
|
||||
# to_user = username
|
||||
# break
|
||||
|
||||
# if to_user:
|
||||
# # Send notification to the user if he replies someone else'
|
||||
# # message.
|
||||
# try:
|
||||
# UserNotification.objects.get(to_user=to_user,
|
||||
# msg_type='innerpubmsg_reply',
|
||||
# detail=innerpub_msg.id)
|
||||
# except UserNotification.DoesNotExist:
|
||||
# n = UserNotification(to_user=to_user,
|
||||
# msg_type='innerpubmsg_reply',
|
||||
# detail=innerpub_msg.id)
|
||||
# n.save()
|
||||
|
||||
# # @receiver(post_save, sender=InnerPubMsg)
|
||||
# def innerpub_msg_added_cb(sender, instance, **kwargs):
|
||||
# from_email = instance.from_email
|
||||
|
||||
# users = get_emailusers(-1, -1)
|
||||
# for u in users:
|
||||
# if u.email == from_email:
|
||||
# continue
|
||||
# try:
|
||||
# UserNotification.objects.get(to_user=u.email,
|
||||
# msg_type='innerpub_msg')
|
||||
# except UserNotification.DoesNotExist:
|
||||
# n = UserNotification(to_user=u.email, msg_type='innerpub_msg',
|
||||
# detail='')
|
||||
# n.save()
|
||||
|
||||
# # @receiver(post_save, sender=InnerPubMsgReply)
|
||||
# def innerpubmsg_reply_added_cb(sender, instance, **kwargs):
|
||||
# innerpub_msg = instance.reply_to
|
||||
# from_email = instance.from_email
|
||||
# msg_id = innerpub_msg.id
|
||||
|
||||
# if from_email == innerpub_msg.from_email:
|
||||
# # No need to send notification when reply own message.
|
||||
# return
|
||||
|
||||
# try:
|
||||
# innerpub_msg = InnerPubMsg.objects.get(id=msg_id)
|
||||
# except InnerPubMsg.DoesNotExist:
|
||||
# pass
|
||||
|
||||
# try:
|
||||
# UserNotification.objects.get(to_user=innerpub_msg.from_email,
|
||||
# msg_type='innerpubmsg_reply',
|
||||
# detail=msg_id)
|
||||
# except UserNotification.DoesNotExist:
|
||||
# n = UserNotification(to_user=innerpub_msg.from_email,
|
||||
# msg_type='innerpubmsg_reply',
|
||||
# detail=msg_id)
|
||||
# n.save()
|
||||
|
@ -150,9 +150,10 @@
|
||||
<table>
|
||||
<tr>
|
||||
<th width="5%"></th>
|
||||
<th width="45%">{% trans "File Name" %}</th>
|
||||
<th width="43%">{% trans "File Name" %}</th>
|
||||
<th width="30%">{% trans "Library" %}</th>
|
||||
<th width="20%">{% trans "Last Update" %}</th>
|
||||
<th width="15%">{% trans "Last Update" %}</th>
|
||||
<th width="12%">{% trans "Operations" %}</th>
|
||||
</tr>
|
||||
{% for sfile in starred_files %}
|
||||
<tr>
|
||||
@ -162,6 +163,9 @@
|
||||
</td>
|
||||
<td>{{ sfile.repo.name }}</td>
|
||||
<td>{{ sfile.last_modified|translate_seahub_time }}</td>
|
||||
<td>
|
||||
<span data-repoid="{{sfile.repo.id}}" data-path="{{sfile.path|urlencode}}" class="icon-trash unstar-btn op-icon vh" title="{% trans "Unstar" %}"></span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
@ -56,6 +56,35 @@
|
||||
window.open('{{ SITE_ROOT }}seafile_access_check/?repo_id=' + $(this).attr('data'));
|
||||
});
|
||||
|
||||
$('.unstar-btn').click(function() {
|
||||
var that = $(this),
|
||||
tr = that.parents('tr'),
|
||||
repo_id = that.data('repoid'),
|
||||
path = that.data('path'),
|
||||
post_url;
|
||||
|
||||
post_url = '{{SITE_ROOT}}ajax/repo/' + repo_id + '/file/unstar/?file=' + path;
|
||||
|
||||
$.ajax({
|
||||
url: post_url,
|
||||
cache: false,
|
||||
dataType: 'json',
|
||||
success:function(data) {
|
||||
if (data['success']) {
|
||||
tr.hide();
|
||||
feedback("{% trans 'Successfully unstarred.' %}", "success");
|
||||
}
|
||||
},
|
||||
error:function(xhr, textStatus, errorThrown) {
|
||||
if (xhr.responseText) {
|
||||
feedback(jQuery.parseJSON(xhr.responseText).error, 'error');
|
||||
} else {
|
||||
feedback("{% trans "Failed. Please check the network." %}", 'error');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("table tr:gt(0)").hover(
|
||||
function() {
|
||||
$(this).find('.op-icon').removeClass('vh');
|
||||
|
@ -407,6 +407,8 @@ 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):
|
||||
"""Calculate file last modification time, and save to db.
|
||||
"""
|
||||
try:
|
||||
# get the lastest one file revision
|
||||
commits = seafserv_threaded_rpc.list_file_revisions(repo_id, file_path, 1, -1)
|
||||
@ -427,7 +429,9 @@ def calc_file_last_modified(repo_id, file_path, file_path_hash, file_id):
|
||||
try:
|
||||
info.save()
|
||||
except IntegrityError:
|
||||
pass
|
||||
# Remove corrupted data, waiting for next insertion.
|
||||
FileLastModifiedInfo.objects.filter(
|
||||
repo_id=repo_id, file_path_hash=file_path_hash).delete()
|
||||
|
||||
return email, last_modified
|
||||
|
||||
@ -541,6 +545,78 @@ def get_file_contributors(repo_id, file_path, file_path_hash, file_id):
|
||||
|
||||
return contributors, last_modified, last_commit_id
|
||||
|
||||
def get_files_last_modified(files_list):
|
||||
"""Batch calculate file last modification file.
|
||||
|
||||
Arguments:
|
||||
- `files_list`: A list contains repo id and file path and file id.
|
||||
|
||||
For example:
|
||||
|
||||
[
|
||||
(u'66a7aaaf-0b59-4c22-9f7a-52606e8fbee3', u'/Chrys (1).jpg', u'c5ee20b7ecf5c44bd184cf64c775aad769f50399'),
|
||||
(u'66a7aaaf-0b59-4c22-9f7a-52606e8fbee3', u'/Chrys (2).jpg', u'd5ee20b7ecf5c44bd184cf64c775aad769f50399'),
|
||||
(u'66a7aaaf-0b59-4c22-9f7a-52606e8fbee3', u'/foo.pdf', u'f78b579f757cec44a99d420331a06ad752b30153'),
|
||||
|
||||
...
|
||||
]
|
||||
|
||||
Returns:
|
||||
A dict mapping keys to the repo id and file path, seperated by "|",
|
||||
and values to the last modification time. For example:
|
||||
|
||||
{
|
||||
u'66a7aaaf-0b59-4c22-9f7a-52606e8fbee3|/Chrys (1).jpg|c5ee20b7ecf5c44bd184cf64c775aad769f50399': 1374549194,
|
||||
u'66a7aaaf-0b59-4c22-9f7a-52606e8fbee3|/Chrys (2).jpg|d5ee20b7ecf5c44bd184cf64c775aad769f50399': 1374585247,
|
||||
u'66a7aaaf-0b59-4c22-9f7a-52606e8fbee3|/foo.pdf|f78b579f757cec44a99d420331a06ad752b30153': 1362471870,
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
"""
|
||||
filepath_hash_set = set()
|
||||
ret_dict = {}
|
||||
|
||||
for e in files_list:
|
||||
repo_id, file_path, file_id = e
|
||||
path_hash = calc_file_path_hash(file_path)
|
||||
filepath_hash_set.add(path_hash)
|
||||
|
||||
m_infos = FileLastModifiedInfo.objects.filter(
|
||||
file_path_hash__in=list(filepath_hash_set))
|
||||
for f in files_list:
|
||||
repo_id, file_path, file_id = f
|
||||
for info in m_infos:
|
||||
if repo_id == info.repo_id and file_path == info.file_path:
|
||||
# Got the record in db
|
||||
ret_key = '|'.join(f)
|
||||
if file_id != info.file_id:
|
||||
# record is outdated, need re-calculate
|
||||
info.delete()
|
||||
email, last_modified = calc_file_last_modified(
|
||||
info.repo_id, info.file_path, info.file_path_hash,
|
||||
file_id)
|
||||
ret_dict[ret_key] = last_modified
|
||||
continue
|
||||
else:
|
||||
# record is valid
|
||||
ret_dict[ret_key] = info.last_modified
|
||||
continue
|
||||
|
||||
# Process the remaining files.
|
||||
for f in files_list:
|
||||
ret_key = '|'.join(f)
|
||||
if ret_dict.has_key(ret_key):
|
||||
continue
|
||||
|
||||
repo_id, file_path, file_id = f
|
||||
path_hash = calc_file_path_hash(file_path)
|
||||
email, last_modified = calc_file_last_modified(
|
||||
repo_id, file_path, path_hash, file_id)
|
||||
ret_dict[ret_key] = last_modified
|
||||
|
||||
return ret_dict
|
||||
|
||||
# events related
|
||||
if EVENTS_CONFIG_FILE:
|
||||
import seafevents
|
||||
@ -652,129 +728,6 @@ else:
|
||||
def get_org_user_events():
|
||||
pass
|
||||
|
||||
class StarredFile(object):
|
||||
def format_path(self):
|
||||
if self.path == "/":
|
||||
return self.path
|
||||
|
||||
# strip leading slash
|
||||
path = self.path[1:]
|
||||
if path[-1:] == '/':
|
||||
path = path[:-1]
|
||||
return path.replace('/', ' / ')
|
||||
|
||||
def __init__(self, org_id, repo, path, is_dir, last_modified, size):
|
||||
# always 0 for non-org repo
|
||||
self.org_id = org_id
|
||||
self.repo = repo
|
||||
self.path = path
|
||||
self.formatted_path = self.format_path()
|
||||
self.is_dir = is_dir
|
||||
# always 0 for dir
|
||||
self.last_modified = last_modified
|
||||
self.size = size
|
||||
if not is_dir:
|
||||
self.name = path.split('/')[-1]
|
||||
|
||||
|
||||
# org_id > 0: get starred files in org repos
|
||||
# org_id < 0: get starred files in personal repos
|
||||
def get_starred_files(email, org_id=-1):
|
||||
"""Return a list of starred files for some user, sorted descending by the
|
||||
last modified time.
|
||||
|
||||
"""
|
||||
starred_files = UserStarredFiles.objects.filter(email=email, org_id=org_id)
|
||||
|
||||
ret = []
|
||||
for sfile in starred_files:
|
||||
# repo still exists?
|
||||
try:
|
||||
repo = get_repo(sfile.repo_id)
|
||||
except SearpcError:
|
||||
continue
|
||||
|
||||
if not repo:
|
||||
sfile.delete()
|
||||
continue
|
||||
|
||||
# file still exists?
|
||||
file_id = ''
|
||||
size = -1
|
||||
if sfile.path != "/":
|
||||
try:
|
||||
file_id = seafserv_threaded_rpc.get_file_id_by_path(sfile.repo_id, sfile.path)
|
||||
size = seafserv_threaded_rpc.get_file_size(file_id)
|
||||
except SearpcError:
|
||||
continue
|
||||
|
||||
if not file_id:
|
||||
sfile.delete()
|
||||
continue
|
||||
|
||||
last_modified = 0
|
||||
if not sfile.is_dir:
|
||||
# last modified
|
||||
path_hash = md5_constructor(urllib2.quote(sfile.path.encode('utf-8'))).hexdigest()[:12]
|
||||
last_modified = get_file_contributors(sfile.repo_id, sfile.path, path_hash, file_id)[1]
|
||||
|
||||
f = StarredFile(sfile.org_id, repo, sfile.path, sfile.is_dir, last_modified, size)
|
||||
|
||||
ret.append(f)
|
||||
ret.sort(lambda x, y: cmp(y.last_modified, x.last_modified))
|
||||
|
||||
return ret
|
||||
|
||||
def star_file(email, repo_id, path, is_dir, org_id=-1):
|
||||
if is_file_starred(email, repo_id, path, org_id):
|
||||
return
|
||||
|
||||
f = UserStarredFiles(email=email,
|
||||
org_id=org_id,
|
||||
repo_id=repo_id,
|
||||
path=path,
|
||||
is_dir=is_dir)
|
||||
try:
|
||||
f.save()
|
||||
except IntegrityError, e:
|
||||
logger.warn(e)
|
||||
|
||||
def unstar_file(email, repo_id, path):
|
||||
# Should use "get", but here we use "filter" to fix the bug caused by no
|
||||
# unique constraint in the table
|
||||
result = UserStarredFiles.objects.filter(email=email,
|
||||
repo_id=repo_id,
|
||||
path=path)
|
||||
for r in result:
|
||||
r.delete()
|
||||
|
||||
def is_file_starred(email, repo_id, path, org_id=-1):
|
||||
# Should use "get", but here we use "filter" to fix the bug caused by no
|
||||
# unique constraint in the table
|
||||
result = UserStarredFiles.objects.filter(email=email,
|
||||
repo_id=repo_id,
|
||||
path=path,
|
||||
org_id=org_id)
|
||||
n = len(result)
|
||||
if n == 0:
|
||||
return False
|
||||
else:
|
||||
# Fix the bug caused by no unique constraint in the table
|
||||
if n > 1:
|
||||
for r in result[1:]:
|
||||
r.delete()
|
||||
return True
|
||||
|
||||
def get_dir_starred_files(email, repo_id, parent_dir, org_id=-1):
|
||||
'''Get starred files under parent_dir.
|
||||
|
||||
'''
|
||||
starred_files = UserStarredFiles.objects.filter(email=email,
|
||||
repo_id=repo_id,
|
||||
path__startswith=parent_dir,
|
||||
org_id=org_id)
|
||||
return [ f.path for f in starred_files ]
|
||||
|
||||
def calc_dir_files_last_modified(repo_id, parent_dir, parent_dir_hash, dir_id):
|
||||
try:
|
||||
ret_list = seafserv_threaded_rpc.calc_files_last_modified(repo_id, parent_dir.encode('utf-8'), 0)
|
||||
@ -1111,4 +1064,4 @@ if EVENTS_CONFIG_FILE:
|
||||
HAS_FILE_SEARCH = check_search_enabled()
|
||||
|
||||
# Move to here to avoid circular import.
|
||||
from seahub.base.models import FileContributors, UserStarredFiles, DirFilesLastModifiedInfo, FileLastModifiedInfo
|
||||
from seahub.base.models import FileContributors, DirFilesLastModifiedInfo, FileLastModifiedInfo
|
||||
|
139
seahub/utils/star.py
Normal file
139
seahub/utils/star.py
Normal file
@ -0,0 +1,139 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import urllib2
|
||||
|
||||
from django.db import IntegrityError
|
||||
from django.utils.hashcompat import md5_constructor
|
||||
|
||||
from pysearpc import SearpcError
|
||||
from seaserv import seafile_api
|
||||
|
||||
from seahub.base.models import UserStarredFiles
|
||||
from seahub.utils import get_file_contributors
|
||||
|
||||
# Get an instance of a logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# class StarredFile(object):
|
||||
# def format_path(self):
|
||||
# if self.path == "/":
|
||||
# return self.path
|
||||
|
||||
# # strip leading slash
|
||||
# path = self.path[1:]
|
||||
# if path[-1:] == '/':
|
||||
# path = path[:-1]
|
||||
# return path.replace('/', ' / ')
|
||||
|
||||
# def __init__(self, org_id, repo, path, is_dir, last_modified, size):
|
||||
# # always 0 for non-org repo
|
||||
# self.org_id = org_id
|
||||
# self.repo = repo
|
||||
# self.path = path
|
||||
# self.formatted_path = self.format_path()
|
||||
# self.is_dir = is_dir
|
||||
# # always 0 for dir
|
||||
# self.last_modified = last_modified
|
||||
# self.size = size
|
||||
# if not is_dir:
|
||||
# self.name = path.split('/')[-1]
|
||||
|
||||
|
||||
# org_id > 0: get starred files in org repos
|
||||
# org_id < 0: get starred files in personal repos
|
||||
# def get_starred_files(email, org_id=-1):
|
||||
# """Return a list of starred files for some user, sorted descending by the
|
||||
# last modified time.
|
||||
|
||||
# """
|
||||
# starred_files = UserStarredFiles.objects.filter(email=email, org_id=org_id)
|
||||
|
||||
# ret = []
|
||||
# for sfile in starred_files:
|
||||
# # repo still exists?
|
||||
# try:
|
||||
# repo = seafile_api.get_repo(sfile.repo_id)
|
||||
# except SearpcError:
|
||||
# continue
|
||||
|
||||
# if not repo:
|
||||
# sfile.delete()
|
||||
# continue
|
||||
|
||||
# # file still exists?
|
||||
# file_id = ''
|
||||
# size = -1
|
||||
# if sfile.path != "/":
|
||||
# try:
|
||||
# file_id = seafile_api.get_file_id_by_path(sfile.repo_id, sfile.path)
|
||||
# size = seafile_api.get_file_size(file_id)
|
||||
# except SearpcError:
|
||||
# continue
|
||||
|
||||
# if not file_id:
|
||||
# sfile.delete()
|
||||
# continue
|
||||
|
||||
# last_modified = 0
|
||||
# if not sfile.is_dir:
|
||||
# # last modified
|
||||
# path_hash = md5_constructor(urllib2.quote(sfile.path.encode('utf-8'))).hexdigest()[:12]
|
||||
# last_modified = get_file_contributors(sfile.repo_id, sfile.path, path_hash, file_id)[1]
|
||||
|
||||
# f = StarredFile(sfile.org_id, repo, sfile.path, sfile.is_dir, last_modified, size)
|
||||
|
||||
# ret.append(f)
|
||||
# ret.sort(lambda x, y: cmp(y.last_modified, x.last_modified))
|
||||
|
||||
# return ret
|
||||
|
||||
def star_file(email, repo_id, path, is_dir, org_id=-1):
|
||||
if is_file_starred(email, repo_id, path, org_id):
|
||||
return
|
||||
|
||||
f = UserStarredFiles(email=email,
|
||||
org_id=org_id,
|
||||
repo_id=repo_id,
|
||||
path=path,
|
||||
is_dir=is_dir)
|
||||
try:
|
||||
f.save()
|
||||
except IntegrityError, e:
|
||||
logger.warn(e)
|
||||
|
||||
def unstar_file(email, repo_id, path):
|
||||
# Should use "get", but here we use "filter" to fix the bug caused by no
|
||||
# unique constraint in the table
|
||||
result = UserStarredFiles.objects.filter(email=email,
|
||||
repo_id=repo_id,
|
||||
path=path)
|
||||
for r in result:
|
||||
r.delete()
|
||||
|
||||
def is_file_starred(email, repo_id, path, org_id=-1):
|
||||
# Should use "get", but here we use "filter" to fix the bug caused by no
|
||||
# unique constraint in the table
|
||||
result = UserStarredFiles.objects.filter(email=email,
|
||||
repo_id=repo_id,
|
||||
path=path,
|
||||
org_id=org_id)
|
||||
n = len(result)
|
||||
if n == 0:
|
||||
return False
|
||||
else:
|
||||
# Fix the bug caused by no unique constraint in the table
|
||||
if n > 1:
|
||||
for r in result[1:]:
|
||||
r.delete()
|
||||
return True
|
||||
|
||||
def get_dir_starred_files(email, repo_id, parent_dir, org_id=-1):
|
||||
'''Get starred files under parent_dir.
|
||||
|
||||
'''
|
||||
starred_files = UserStarredFiles.objects.filter(email=email,
|
||||
repo_id=repo_id,
|
||||
path__startswith=parent_dir,
|
||||
org_id=org_id)
|
||||
return [ f.path for f in starred_files ]
|
||||
|
@ -53,7 +53,8 @@ from pysearpc import SearpcError
|
||||
|
||||
from seahub.base.accounts import User
|
||||
from seahub.base.decorators import sys_staff_required
|
||||
from seahub.base.models import UuidObjidMap, InnerPubMsg, InnerPubMsgReply
|
||||
from seahub.base.models import UuidObjidMap, InnerPubMsg, InnerPubMsgReply, \
|
||||
UserStarredFiles
|
||||
from seahub.contacts.models import Contact
|
||||
from seahub.contacts.signals import mail_sended
|
||||
from seahub.group.forms import MessageForm, MessageReplyForm
|
||||
@ -75,10 +76,10 @@ from seahub.utils import render_permission_error, render_error, list_to_string,
|
||||
gen_file_get_url, string2list, MAX_INT, IS_EMAIL_CONFIGURED, \
|
||||
gen_file_upload_url, check_and_get_org_by_repo, \
|
||||
get_file_contributors, EVENTS_ENABLED, get_user_events, get_org_user_events, \
|
||||
get_starred_files, star_file, unstar_file, is_file_starred, get_dir_starred_files, \
|
||||
get_dir_files_last_modified, show_delete_days, \
|
||||
TRAFFIC_STATS_ENABLED, get_user_traffic_stat
|
||||
from seahub.utils.paginator import get_page_range
|
||||
from seahub.utils.star import get_dir_starred_files
|
||||
|
||||
from seahub.utils import HAS_OFFICE_CONVERTER
|
||||
|
||||
@ -878,7 +879,8 @@ def myhome(request):
|
||||
|
||||
allow_public_share = False if request.cloud_mode else True
|
||||
|
||||
starred_files = get_starred_files(request.user.username)
|
||||
starred_files = UserStarredFiles.objects.get_starred_files_by_username(
|
||||
request.user.username)
|
||||
|
||||
traffic_stat = 0
|
||||
if TRAFFIC_STATS_ENABLED:
|
||||
|
@ -22,7 +22,8 @@ from seahub.views import get_repo_dirents
|
||||
from seahub.views.repo import get_nav_path, get_fileshare, get_dir_share_link
|
||||
import seahub.settings as settings
|
||||
from seahub.signals import repo_created
|
||||
from seahub.utils import check_filename_with_rename, star_file, unstar_file
|
||||
from seahub.utils import check_filename_with_rename
|
||||
from seahub.utils.star import star_file, unstar_file
|
||||
|
||||
# Get an instance of a logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -39,12 +39,13 @@ from seahub.share.models import FileShare, PrivateFileDirShare
|
||||
from seahub.wiki.utils import get_wiki_dirent
|
||||
from seahub.wiki.models import WikiDoesNotExist, WikiPageMissing
|
||||
from seahub.utils import show_delete_days, render_error, \
|
||||
get_file_type_and_ext, gen_file_get_url, gen_file_share_link, is_file_starred, \
|
||||
get_file_type_and_ext, gen_file_get_url, gen_file_share_link, \
|
||||
get_file_contributors, get_ccnetapplet_root, render_permission_error, \
|
||||
is_textual_file, show_delete_days, mkstemp, EMPTY_SHA1, HtmlDiff, \
|
||||
check_filename_with_rename, gen_inner_file_get_url, normalize_file_path
|
||||
from seahub.utils.file_types import (IMAGE, PDF, IMAGE, DOCUMENT, MARKDOWN, \
|
||||
TEXT, SF)
|
||||
from seahub.utils.star import is_file_starred
|
||||
from seahub.utils import HAS_OFFICE_CONVERTER
|
||||
|
||||
if HAS_OFFICE_CONVERTER:
|
||||
|
Loading…
Reference in New Issue
Block a user