1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-06 17:33:18 +00:00

Add contact and share app

This commit is contained in:
plt
2012-02-11 11:12:54 +08:00
parent fe1b85dbd6
commit 67e0ce2fb6
24 changed files with 406 additions and 39 deletions

0
contacts/__init__.py Normal file
View File

14
contacts/forms.py Normal file
View File

@@ -0,0 +1,14 @@
from django import forms
class AddContactForm(forms.Form):
"""
Form for adding a contact.
"""
email = forms.EmailField()
def __init__(self, *args, **kwargs):
super(AddContactForm, self).__init__(*args, **kwargs)

11
contacts/models.py Normal file
View File

@@ -0,0 +1,11 @@
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
class Contact(models.Model):
"""Record user's contacts."""
owner = models.ForeignKey(User, related_name="contacts")
user = models.ForeignKey(User, related_name="contacts2me")

View File

@@ -0,0 +1,22 @@
{% extends "myhome_base.html" %}
{% block left_panel %}
<ul>
<li><a href="{{ SITE_ROOT }}contacts/list/">联系人列表</a></li>
</ul>
{% endblock %}
{% block right_panel %}
<h2>添加联系人</h2>
<form action="" method="post">
{% if error_msg %}
<p class="error">{{ error_msg }}</p>
{% endif %}
<label>Email:</label><br/>
{{ form.email }}<br/>
<input type="submit" value="提交" />
</form>
{% endblock %}

View File

@@ -0,0 +1,21 @@
{% extends "myhome_base.html" %}
{% block left_panel %}
<ul>
<li><a href="{{ SITE_ROOT }}contacts/add/">添加联系人</a></li>
</ul>
{% endblock %}
{% block right_panel %}
<h2>联系人列表</h2>
<table class="contact-list default">
{% for contact in contacts %}
<tr>
<td>{{ contact.user.email }}</td>
<td><a href="{{ SITE_ROOT }}share/add/?user_email={{ contact.user.email|urlencode }}">共享</a></td>
</tr>
{% endfor %}
</table>
{% endblock %}

11
contacts/urls.py Normal file
View File

@@ -0,0 +1,11 @@
from django.conf.urls.defaults import *
from views import *
urlpatterns = patterns('',
url(r'^$', contact_list),
url(r'^list/$', contact_list, name='contact_list'),
url(r'^add/$', contact_add, name='contact_add'),
url(r'^delete/$', contact_delete, name='contact_delete'),
)

45
contacts/views.py Normal file
View File

@@ -0,0 +1,45 @@
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.core.urlresolvers import reverse
from django.template import RequestContext
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from models import Contact
from forms import AddContactForm
@login_required
def contact_list(request):
contacts = Contact.objects.filter(owner=request.user)
return render_to_response('contacts/contact_list.html', {
'contacts': contacts,
}, context_instance=RequestContext(request))
@login_required
def contact_add(request):
error_msg = None
if request.method == 'POST':
form = AddContactForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
try:
user = User.objects.get(email=email)
contact = Contact()
contact.owner = request.user
contact.user = user
contact.save()
return HttpResponseRedirect(reverse("contact_list"))
except ObjectDoesNotExist:
error_msg = "No user with email \"%s\"" % (email)
else:
form = AddContactForm()
return render_to_response('contacts/contact_add.html', {
'form': form,
}, context_instance=RequestContext(request))
@login_required
def contact_delete(request):
return HttpResponseRedirect(request.META['HTTP_REFERER'])

View File

@@ -1,15 +0,0 @@
from django import forms
from models import GroupRepo
class GroupAddRepoForm(forms.Form):
"""
Form for adding repo to a group.
"""
repo_id = forms.CharField(max_length=36)
def __init__(self, *args, **kwargs):
super(GroupAddRepoForm, self).__init__(*args, **kwargs)

View File

@@ -1,13 +1,33 @@
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
# Create your models here.
class GroupRepo(models.Model):
"""A repo shared to a group."""
class Group(models.Model):
"""A group is identified uniquely by group_id."""
group_id = models.CharField(max_length=36)
repo_id = models.CharField(max_length=36)
repo_location = models.CharField(max_length=40, blank=True)
group_id = models.CharField(max_length=36, primary_key=True, db_column='uuid')
name = models.CharField(max_length=20, editable=False, unique=True)
creator = models.ForeignKey(User, verbose_name=_("creator"), related_name="%(class)s_created")
admin = models.ForeignKey(User, verbose_name=_("admin"), related_name="%(class)s_admined")
ctime = models.DateTimeField('create time', editable=False)
description = models.TextField(_("description"))
users = models.ManyToManyField(User)
class Meta:
unique_together = ("group_id", "repo_id")
def __unicode__(self):
return self.name
class JoinRequest(models.Model):
"""A request for joining a group."""
group = models.ForeignKey(Group)
user = models.ForeignKey(User)
ctime = models.DateTimeField('create time', editable=False)
class Invitation(models.Model):
"""An invitation for joining a group."""
group = models.ForeignKey(Group)
user = models.ForeignKey(User)
ctime = models.DateTimeField('create time', editable=False)

View File

@@ -1 +1,4 @@
# Create your views here.
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User

View File

@@ -144,4 +144,6 @@ strong { color:#808; font-weight: normal; }
div.home-page h2 { font-style: italic; }
/* help pages */
.help-page { width: 550px; }
.help-page img { display: block; margin: 20px auto; }
.help-page img { display: block; margin: 20px auto; }
#id_repo_id { width:300px; }

View File

@@ -102,7 +102,9 @@ INSTALLED_APPS = (
'avatar',
'seahub.base',
'seahub.profile',
'seahub.contacts',
'seahub.group',
'seahub.share',
)
AUTHENTICATION_BACKENDS = (

0
share/__init__.py Normal file
View File

43
share/forms.py Normal file
View File

@@ -0,0 +1,43 @@
from django import forms
from django.contrib.auth.models import User
class GroupAddRepoForm(forms.Form):
"""
Form for adding repo to a group.
"""
repo_id = forms.CharField(max_length=36)
def __init__(self, *args, **kwargs):
super(GroupAddRepoForm, self).__init__(*args, **kwargs)
class UserShareForm(forms.Form):
"""
Form for sharing repo to a user.
"""
user_email = forms.EmailField()
repo_id = forms.CharField(max_length=36)
def __init__(self, *args, **kwargs):
super(UserShareForm, self).__init__(*args, **kwargs)
def clean_user_email(self):
data = self.cleaned_data['user_email']
try:
# put the user in form.to_user for further use
self.to_user = User.objects.get(email=data)
except User.DoesNotExist:
raise forms.ValidationError("No user with such email")
return data
def clean_repo_id(self):
data = self.cleaned_data['repo_id']
if len(data) != 36:
raise forms.ValidationError("Invalid repo id")
return data

19
share/models.py Normal file
View File

@@ -0,0 +1,19 @@
from django.db import models
from django.contrib.auth.models import User
class UserShare(models.Model):
"""Record a repo shared to a user."""
from_user = models.ForeignKey(User, related_name="myshare_items")
to_user = models.ForeignKey(User, related_name="share2me_items")
repo_id = models.CharField(max_length=36)
class GroupShare(models.Model):
"""A repo shared to a group."""
group_id = models.CharField(max_length=36)
repo_id = models.CharField(max_length=36)
class Meta:
unique_together = ("group_id", "repo_id")

View File

@@ -0,0 +1,25 @@
{% extends "myhome_base.html" %}
{% block left_panel %}
<ul>
<li><a href="{{ SITE_ROOT }}share/list/">共享列表</a></li>
<li>共享同步目录</li>
</ul>
{% endblock %}
{% block right_panel %}
<h2>共享同步目录</h2>
<form action="" method="post">
{{ form.non_field_errors }}
{{ form.user_email.errors }}
<label>联系人 Email:</label><br/>
{{ form.user_email }}<br />
{{ form.repo_id.errors }}
<label>同步目录 ID:</label><br/>
{{ form.repo_id }}<br />
<input type="submit" value="Submit" />
</form>
{% endblock %}

View File

@@ -0,0 +1,46 @@
{% extends "myhome_base.html" %}
{% block left_panel %}
<ul>
<li>共享列表</li>
<li><a href="{{ SITE_ROOT }}share/add/">共享同步目录</a></li>
</ul>
{% endblock %}
{% block right_panel %}
<h2>共享给我的同步目录</h2>
<table class="repo-list default">
<tr>
<th>共享人</th>
<th>ID</th>
<th>操作</th>
</tr>
{% for item in share2me_items %}
<tr>
<td>{{ item.from_user.email }}</td>
<td><a href="{{ SITE_ROOT }}repo/{{ item.repo_id }}/">{{ item.repo_id }}</a></td>
<td>
</td>
</tr>
{% endfor %}
</table>
<h2>所有共享的同步目录</h2>
<table class="repo-list default">
<tr>
<th>共享给</th>
<th>ID</th>
<th>操作</th>
</tr>
{% for item in share_items %}
<tr>
<td>{{ item.to_user.email }}</td>
<td><a href="{{ SITE_ROOT }}repo/{{ item.repo_id }}/">{{ item.repo_id }}</a></td>
<td><a href="{{ SITE_ROOT }}share/delete/{{ item.id }}/">删除</a>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

23
share/tests.py Normal file
View File

@@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

11
share/urls.py Normal file
View File

@@ -0,0 +1,11 @@
from django.conf.urls.defaults import *
from views import *
urlpatterns = patterns('',
url(r'^$', list_shared_repos),
url(r'^list/$', list_shared_repos, name='shared_repo_list'),
url(r'^add/$', share_repo),
url(r'^delete/(?P<item_id>[^/]+)/$', delete_share_item),
)

62
share/views.py Normal file
View File

@@ -0,0 +1,62 @@
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.core.urlresolvers import reverse
from django.template import RequestContext
from django.contrib.auth.decorators import login_required
from forms import UserShareForm
from models import UserShare
@login_required
def list_shared_repos(request):
"""Show the repos I shared."""
share_items = UserShare.objects.filter(from_user=request.user)
share2me_items = UserShare.objects.filter(to_user=request.user)
#for repo in s_repos:
# s_repos
# pass
return render_to_response("repo/shared_repo_list.html",
{ 'share_items': share_items,
"share2me_items": share2me_items },
context_instance=RequestContext(request))
@login_required
def share_repo(request):
"""Share a repo to a user."""
if request.method == 'POST':
form = UserShareForm(request.POST)
if form.is_valid():
repo_share = UserShare()
repo_share.from_user = request.user
repo_share.to_user = form.to_user
repo_share.repo_id = form.cleaned_data['repo_id']
try:
repo_share.save()
except IntegrityError:
# catch the case repo added to group before
pass
return HttpResponseRedirect(reverse('shared_repo_list', args=[]))
else:
user_email = request.REQUEST.get('user_email', '')
repo_id = request.REQUEST.get('repo_id', '')
form = UserShareForm(initial={'user_email': user_email, 'repo_id': repo_id})
return render_to_response("repo/share_repo.html", {
'form': form,
}, context_instance=RequestContext(request))
@login_required
def delete_share_item(request, item_id):
"""Delete a share item."""
try:
item = UserShare.objects.get(pk=item_id)
item.delete()
except UserShare.DoesNotExist:
pass
return HttpResponseRedirect(request.META['HTTP_REFERER'])

View File

@@ -20,7 +20,7 @@
<div class="top-bar">
<div class="top-bar-in">
{% if request.user.is_authenticated %}
欢迎, {{ request.user }}.
欢迎, {{ request.user.email }}
<a href="{{ SITE_ROOT }}profile/">设置</a>
{% if request.user.is_staff %}
<a href="{{ SITE_ROOT }}admin/">管理</a>

View File

@@ -4,6 +4,12 @@
<li>
<a href="{{ SITE_ROOT }}home/my/">我的页面</a>
</li>
<li>
<a href="{{ SITE_ROOT }}share/">共享</a>
</li>
<li>
<a href="{{ SITE_ROOT }}contacts/">联系人</a>
</li>
{% if request.user.is_staff %}
<li>
<a href="{{ SITE_ROOT }}seafadmin/">中继管理</a>

View File

@@ -32,6 +32,9 @@ urlpatterns = patterns('',
(r'^seafadmin/$', seafadmin),
(r'^avatar/', include('avatar.urls')),
(r'^profile/', include('seahub.profile.urls')),
(r'^contacts/', include('contacts.urls')),
(r'^share/', include('share.urls')),
)
if settings.DEBUG:

View File

@@ -10,17 +10,10 @@ from seaserv import cclient, ccnet_rpc, get_groups, get_users, get_repos, \
seafserv_rpc
from seahub.profile.models import UserProfile
from seahub.group.models import GroupRepo
from seahub.group.forms import GroupAddRepoForm
from seahub.share.models import GroupShare, UserShare
from seahub.share.forms import GroupAddRepoForm
def get_user_cid(user):
try:
profile = user.get_profile()
return profile.ccnet_user_id
except UserProfile.DoesNotExist:
return None
@login_required
def root(request):
return HttpResponseRedirect(reverse(myhome))
@@ -62,7 +55,7 @@ def group(request, group_id):
"""
group = get_group(group_id)
shared_repos = GroupRepo.objects.filter(group_id=group_id)
shared_repos = GroupShare.objects.filter(group_id=group_id)
return render_to_response('group.html', {
'group': group, 'shared_repos': shared_repos,
}, context_instance=RequestContext(request))
@@ -78,7 +71,7 @@ def group_add_repo(request, group_id):
if request.method == 'POST':
form = GroupAddRepoForm(request.POST)
if form.is_valid():
group_repo = GroupRepo()
group_repo = GroupShare()
group_repo.group_id = group_id
group_repo.repo_id = form.cleaned_data['repo_id']
try:
@@ -105,7 +98,7 @@ def repo(request, repo_id):
token = ""
is_owner = False
if request.user.is_authenticated():
cid = get_user_cid(request.user)
cid = request.user.user_id
if seafserv_rpc.is_repo_owner(cid, repo_id):
is_owner = True
token = seafserv_rpc.get_repo_token(repo_id)
@@ -129,7 +122,7 @@ def repo_share(request, repo_id):
@login_required
def modify_token(request, repo_id):
cid = get_user_cid(request.user)
cid = request.user.user_id
if not seafserv_rpc.is_repo_owner(cid, repo_id):
return HttpResponseRedirect(reverse(repo, args=[repo_id]))