mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-30 12:56:46 +00:00
Merge branch 'personal-wiki'
This commit is contained in:
commit
d76e6b0566
@ -821,6 +821,20 @@ textarea:-moz-placeholder {/* for FF */
|
||||
|
||||
/* for separate pages */
|
||||
/*myhome*/
|
||||
.personal-nav {
|
||||
border-bottom:1px solid #ddd;
|
||||
margin-bottom:16px;
|
||||
margin-top:-12px;
|
||||
text-align:right;
|
||||
}
|
||||
.personal-nav .item {
|
||||
float:left;
|
||||
font-size:15px;
|
||||
margin:8px 16px 0 0;
|
||||
}
|
||||
.personal-nav a {
|
||||
font-weight:normal;
|
||||
}
|
||||
.home-profile .pic {
|
||||
margin-left:9px;
|
||||
}
|
||||
|
@ -131,6 +131,7 @@ INSTALLED_APPS = (
|
||||
|
||||
'seahub.base',
|
||||
'seahub.contacts',
|
||||
'seahub.wiki',
|
||||
'seahub.group',
|
||||
'seahub.notifications',
|
||||
# 'seahub.organizations',
|
||||
|
@ -5,6 +5,19 @@
|
||||
{% block sub_title %}{% trans "My Home" %} - {% endblock %}
|
||||
{% block nav_myhome_class %}class="cur"{% endblock %}
|
||||
|
||||
|
||||
{% block title_panel %}
|
||||
|
||||
<div class="tabnav">
|
||||
<ul class="tabnav-tabs">
|
||||
<li class="tabnav-tab tabnav-tab-cur">{% trans "Libraries" %}</li>
|
||||
<li class="tabnav-tab"><a href="{% url 'personal_wiki' %}">{% trans "Personal Wiki" %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block left_panel %}
|
||||
<div class="info-item">
|
||||
<h3 class="info-item-top">{% trans "Account" %}</h3>
|
||||
|
@ -1,6 +1,5 @@
|
||||
{% load seahub_tags i18n %}
|
||||
{% load url from future %}
|
||||
<h3>{% trans "Libraries" %}</h3>
|
||||
<div id="tabs">
|
||||
<div class="ovhd">
|
||||
<ul class="fleft" id="tabs-nav">
|
||||
|
146
templates/wiki/personal_wiki.html
Normal file
146
templates/wiki/personal_wiki.html
Normal file
@ -0,0 +1,146 @@
|
||||
{% extends "myhome_base.html" %}
|
||||
|
||||
{% load seahub_tags avatar_tags i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block sub_title %}{% trans "Personal Wiki" %}{% endblock %}
|
||||
{% block nav_myhome_class %}class="cur"{% endblock %}
|
||||
|
||||
{% block title_panel %}
|
||||
|
||||
<div class="tabnav">
|
||||
<ul class="tabnav-tabs">
|
||||
<li class="tabnav-tab"><a href="{% url 'myhome' %}">{% trans "Libraries" %}</a></li>
|
||||
<li class="tabnav-tab tabnav-tab-cur">{% trans "Personal Wiki" %}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block main_panel %}
|
||||
|
||||
{% if not wiki_exists %}
|
||||
<div class="empty-tips">
|
||||
<h2 class="center-contents">{% trans "You do not have personal wiki" %}</h2>
|
||||
<p>{% trans "Seafile Wiki enables you to take notes in a simple way. The contents of wiki is stored in a normal library with pre-defined file/folder structure. This enables you to edit your wiki in your desktop and then sync back to the server." %}</p>
|
||||
<a id="wiki-create" href="#">{% trans "Create Wiki Now" %}</a>
|
||||
</div>
|
||||
<form id="wiki-create-form" action="" method="post" class="hide">
|
||||
<h3>{% trans "Create Wiki" %}</h3>
|
||||
<label>{% trans "Name" %}</label><br/>
|
||||
<input id="repo-name" type="text" name="repo_name" value="personal-wiki" maxlength="{{max_file_name}}"/><br />
|
||||
<label>{% trans "Description" %}</label><br/>
|
||||
<textarea id="repo-desc" name="repo_desc">{% trans "Personal Wiki Pages" %}</textarea><br/>
|
||||
<p class="error hide"></p>
|
||||
<input type="submit" id="wiki-create-submit" value="{% trans "Submit"%}" class="submit" />
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
<div class="wiki-top w100 ovhd">
|
||||
<ul class="wiki-nav fleft">
|
||||
<li class="item"><a href="{% url 'personal_wiki' %}" class="link">{% trans "Home" %}</a></li>
|
||||
<li class="item"><a href="{% url 'personal_wiki_pages' %}" class="link">{% trans "Pages" %}</a></li>
|
||||
{% if group.view_perm != "pub" %}
|
||||
<li class="item"><a href="{% url 'repo_history' repo_id %}" target="_blank" class="link">{% trans "Wiki History" %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<button id="page-create" class="op-btn">{% trans "New Page" %}</button>
|
||||
<button id="page-delete" class="op-btn" data-url="{% url 'personal_wiki_page_delete' page %}">{% trans "Delete Page" %}</button>
|
||||
<button id="page-edit" class="op-btn">{% trans "Edit Page" %}</button>
|
||||
<button id="page-history" class="op-btn">{% trans "Page History" %}</button>
|
||||
</div>
|
||||
|
||||
<div id="wiki-area" class="article">
|
||||
<h1>{{ page|capfirst }}</h1>
|
||||
<div id="wiki-content"></div><!--content will be offered by js-->
|
||||
<p id="wiki-last-modified">{% blocktrans with modifier=latest_contributor|email2nickname modify_time=last_modified|translate_seahub_time %}Last modified by {{modifier}}, {{modify_time}}{% endblocktrans %}</p>
|
||||
</div>
|
||||
|
||||
<form id="page-create-form" action="{% url 'personal_wiki_page_new' %}" method="post" class="simple-input-popup hide">
|
||||
<h3>{% trans "New Page"%}</h3>
|
||||
<label>{% trans "Name"%}</label><br/>
|
||||
<input id="page-name" type="text" name="page_name" value="" maxlength="{{max_file_name}}" class="long-input" /><br />
|
||||
<p class="error hide"></p>
|
||||
<input type="submit" id="page-create-submit" value="{% trans "Submit"%}" class="submit"/>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock main_panel %}
|
||||
|
||||
{% block extra_script %}
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/Markdown.Converter.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/Markdown.Extra.js"></script>
|
||||
<script type="text/javascript">
|
||||
{% if wiki_exists %}
|
||||
var converter = new Markdown.Converter();
|
||||
Markdown.Extra.init(converter, {extensions: ["fenced_code_gfm"]});
|
||||
$('#wiki-content').html(converter.makeHtml('{{ content|escapejs }}')).children(':first').css('margin-top', '0');
|
||||
|
||||
$('#page-create').click(function() {
|
||||
$('#page-create-form').modal({appendTo: '#main', autoResize: true});
|
||||
})
|
||||
|
||||
$('#page-edit').click(function() {
|
||||
location.href = ("{% url 'personal_wiki_page_edit' page %}");
|
||||
})
|
||||
|
||||
$('#page-list').click(function () {
|
||||
location.href = ("{% url 'personal_wiki_pages' %}");
|
||||
});
|
||||
|
||||
$('#page-history').click(function () {
|
||||
window.open("{% url 'file_revisions' repo_id %}" + "?p=" + "{{path|urlencode}}");
|
||||
});
|
||||
|
||||
addConfirmTo($('#page-delete'), {
|
||||
'title': 'Delete Page',
|
||||
'con': 'Are you sure you want to delete this page?'
|
||||
});
|
||||
$('a.wiki-page-missing').each(function(){
|
||||
$(this).click(function() {
|
||||
$('#page-name').val($(this).text());
|
||||
$('#page-create-form').modal({appendTo: '#main', autoResize: true});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
{% else %}
|
||||
$('#wiki-create').click(function() {
|
||||
$('#wiki-create-form').modal({appendTo: '#main', autoResize: true});
|
||||
return false;
|
||||
});
|
||||
$('#wiki-create-submit').click(function () {
|
||||
if (!$.trim($('#repo-name').val()) || !$.trim($('#repo-desc').val())) {
|
||||
apply_form_error('wiki-create-form', '{% trans 'Name and description can not be blank.' %}');
|
||||
return false;
|
||||
}
|
||||
|
||||
var submit_btn = $(this);
|
||||
disable(submit_btn);
|
||||
$.ajax({
|
||||
url: '{% url 'personal_wiki_create' %}',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
beforeSend: prepareCSRFToken,
|
||||
data: {
|
||||
'repo_name': $('#repo-name').val(),
|
||||
'repo_desc': $('#repo-desc').val()
|
||||
},
|
||||
success: function(data) {
|
||||
location.href = data['href'];
|
||||
},
|
||||
error: function(data, textStatus, jqXHR) {
|
||||
var errors = $.parseJSON(data.responseText);
|
||||
$.each(errors, function(index, value) {
|
||||
apply_form_error('wiki-create-form', value);
|
||||
});
|
||||
enable(submit_btn);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
{% endif %} // END wiki_exists
|
||||
</script>
|
||||
{% endblock %}
|
53
templates/wiki/personal_wiki_pages.html
Normal file
53
templates/wiki/personal_wiki_pages.html
Normal file
@ -0,0 +1,53 @@
|
||||
{% extends "myhome_base.html" %}
|
||||
|
||||
{% load seahub_tags avatar_tags group_avatar_tags i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block sub_title %}{% trans "Personal Wiki" %}{% endblock %}
|
||||
{% block nav_myhome_class %}class="cur"{% endblock %}
|
||||
|
||||
{% block title_panel %}
|
||||
|
||||
<div class="tabnav">
|
||||
<ul class="tabnav-tabs">
|
||||
<li class="tabnav-tab"><a href="{% url 'myhome' %}">{% trans "Libraries" %}</a></li>
|
||||
<li class="tabnav-tab tabnav-tab-cur">{% trans "Personal Wiki" %}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block main_panel %}
|
||||
|
||||
<div class="wiki-top w100 ovhd">
|
||||
<ul class="wiki-nav fleft">
|
||||
<li class="item"><a href="{% url 'personal_wiki' %}" class="link">{% trans "Home" %}</a></li>
|
||||
<li class="item"><a href="{% url 'personal_wiki_pages' %}" class="link">{% trans "Pages" %}</a></li>
|
||||
<li class="item"><a href="{% url 'repo_history' repo_id %}" target="_blank" class="link">{% trans "Wiki History" %}</a></li>
|
||||
</ul>
|
||||
<button id="page-create" class="op-btn">{% trans "New Page" %}</button>
|
||||
</div>
|
||||
|
||||
<ul id="wiki-pages">
|
||||
{% for page_slug, page in pages.items %}
|
||||
<li><a href="{% url 'personal_wiki' page_slug %}">{{ page }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<form id="page-create-form" action="{% url 'personal_wiki_page_new' %}" method="post" class="hide">
|
||||
<h3>{% trans "New Page"%}</h3>
|
||||
<label>{% trans "Name"%}</label><br/>
|
||||
<input id="page-name" type="text" name="page_name" value="" maxlength="{{max_file_name}}"/><br />
|
||||
<p class="error hide"></p>
|
||||
<input type="submit" id="page-create-submit" value="{% trans "Submit"%}" class="submit" />
|
||||
</form>
|
||||
|
||||
{% endblock main_panel %}
|
||||
|
||||
{% block extra_script %}
|
||||
<script type="text/javascript">
|
||||
$('#page-create').click(function() {
|
||||
$('#page-create-form').modal({appendTo: '#main', autoResize: true});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
11
urls.py
11
urls.py
@ -9,6 +9,9 @@ from seahub.views.repo import RepoView, RepoHistoryView
|
||||
from seahub.views.search import search
|
||||
from notifications.views import notification_list
|
||||
from group.views import group_list
|
||||
from seahub.views.wiki import personal_wiki, personal_wiki_pages, \
|
||||
personal_wiki_create, personal_wiki_page_new, personal_wiki_page_edit, \
|
||||
personal_wiki_page_delete
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
#from django.contrib import admin
|
||||
@ -30,6 +33,14 @@ urlpatterns = patterns('',
|
||||
(r'^$', root),
|
||||
#url(r'^home/$', direct_to_template, { 'template': 'home.html' } ),
|
||||
url(r'^home/my/$', myhome, name='myhome'),
|
||||
url(r'^home/wiki/$', personal_wiki, name='personal_wiki'),
|
||||
url(r'^home/wiki/(?P<page_name>[^/]+)/$', personal_wiki, name='personal_wiki'),
|
||||
url(r'^home/wiki_pages/$', personal_wiki_pages, name='personal_wiki_pages'),
|
||||
url(r'^home/wiki_create/$', personal_wiki_create, name='personal_wiki_create'),
|
||||
url(r'^home/wiki_page_new/$', personal_wiki_page_new, name='personal_wiki_page_new'),
|
||||
url(r'^home/wiki_page_edit/(?P<page_name>[^/]+)$', personal_wiki_page_edit, name='personal_wiki_page_edit'),
|
||||
url(r'^home/wiki_page_delete/(?P<page_name>[^/]+)$', personal_wiki_page_delete, name='personal_wiki_page_delete'),
|
||||
|
||||
url(r'^home/public/reply/(?P<msg_id>[\d]+)/$', innerpub_msg_reply, name='innerpub_msg_reply'),
|
||||
url(r'^home/owner/(?P<owner_name>[^/]+)/$', ownerhome, name='ownerhome'),
|
||||
|
||||
|
190
views/wiki.py
Normal file
190
views/wiki.py
Normal file
@ -0,0 +1,190 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
File related views, including view_file, edit_file, view_history_file,
|
||||
view_trash_file, view_snapshot_file
|
||||
"""
|
||||
|
||||
import os
|
||||
import simplejson as json
|
||||
import stat
|
||||
import tempfile
|
||||
import urllib
|
||||
import urllib2
|
||||
import chardet
|
||||
|
||||
from django.contrib.sites.models import Site, RequestSite
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, Http404, \
|
||||
HttpResponseRedirect
|
||||
from django.shortcuts import render_to_response, redirect
|
||||
from django.template import Context, loader, RequestContext
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.hashcompat import md5_constructor
|
||||
from django.utils.http import urlquote
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from auth.decorators import login_required
|
||||
|
||||
import seaserv
|
||||
from pysearpc import SearpcError
|
||||
|
||||
|
||||
from seahub.wiki.models import PersonalWiki, WikiDoesNotExist, WikiPageMissing
|
||||
from seahub.wiki import get_personal_wiki_page, get_personal_wiki_repo, \
|
||||
convert_wiki_link, get_wiki_pages
|
||||
from seahub.wiki.forms import WikiCreateForm, WikiNewPageForm
|
||||
from seahub.utils import get_file_contributors, render_error
|
||||
|
||||
@login_required
|
||||
def personal_wiki(request, page_name="home"):
|
||||
username = request.user.username
|
||||
wiki_exists = True
|
||||
try:
|
||||
content, repo, dirent = get_personal_wiki_page(username, page_name)
|
||||
except WikiDoesNotExist:
|
||||
wiki_exists = False
|
||||
return render_to_response("wiki/personal_wiki.html", {
|
||||
"wiki_exists": wiki_exists,
|
||||
}, context_instance=RequestContext(request))
|
||||
except WikiPageMissing:
|
||||
repo = get_personal_wiki_repo(username)
|
||||
filename = clean_page_name(page_name) + '.md'
|
||||
if not post_empty_file(repo.id, "/", filename, username):
|
||||
return render_error(request, _("Failed to create wiki page. Please retry later."))
|
||||
return HttpResponseRedirect(reverse('personal_wiki', args=[page_name]))
|
||||
else:
|
||||
url_prefix = reverse('personal_wiki', args=[])
|
||||
content = convert_wiki_link(content, url_prefix, repo.id, username)
|
||||
|
||||
# fetch file latest contributor and last modified
|
||||
path = '/' + dirent.obj_name
|
||||
file_path_hash = md5_constructor(urllib2.quote(path.encode('utf-8'))).hexdigest()[:12]
|
||||
contributors, last_modified, last_commit_id = get_file_contributors(\
|
||||
repo.id, path.encode('utf-8'), file_path_hash, dirent.obj_id)
|
||||
latest_contributor = contributors[0] if contributors else None
|
||||
|
||||
return render_to_response("wiki/personal_wiki.html", {
|
||||
"wiki_exists": wiki_exists,
|
||||
"content": content,
|
||||
"page": os.path.splitext(dirent.obj_name)[0],
|
||||
"last_modified": last_modified,
|
||||
"latest_contributor": latest_contributor,
|
||||
"path": path,
|
||||
"repo_id": repo.id,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
@login_required
|
||||
def personal_wiki_pages(request):
|
||||
"""
|
||||
List personal wiki pages.
|
||||
"""
|
||||
try:
|
||||
repo = get_personal_wiki_repo(request.user.username)
|
||||
pages = get_wiki_pages(repo)
|
||||
except SearpcError:
|
||||
return render_error(request, _('Internal Server Error'))
|
||||
except WikiDoesNotExist:
|
||||
return render_error(request, _('Wiki does not exists.'))
|
||||
|
||||
return render_to_response("wiki/personal_wiki_pages.html", {
|
||||
"pages": pages,
|
||||
"repo_id": repo.id
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def personal_wiki_create(request):
|
||||
if request.method != 'POST':
|
||||
raise Http404
|
||||
|
||||
content_type = 'application/json; charset=utf-8'
|
||||
|
||||
def json_error(err_msg, status=400):
|
||||
result = {'error': err_msg}
|
||||
return HttpResponse(json.dumps(result), status=status,
|
||||
content_type=content_type)
|
||||
|
||||
form = WikiCreateForm(request.POST)
|
||||
if not form.is_valid():
|
||||
return json_error(str(form.errors.values()[0]))
|
||||
|
||||
# create group repo in user context
|
||||
repo_name = form.cleaned_data['repo_name']
|
||||
repo_desc = form.cleaned_data['repo_desc']
|
||||
username = request.user.username
|
||||
passwd = None
|
||||
permission = "rw"
|
||||
|
||||
repo_id = seaserv.create_repo(repo_name, repo_desc, username, passwd)
|
||||
if not repo_id:
|
||||
return json_error(_(u'Failed to create'), 500)
|
||||
|
||||
PersonalWiki.objects.save_personal_wiki(username=username, repo_id=repo_id)
|
||||
|
||||
# create home page
|
||||
page_name = "home.md"
|
||||
if not seaserv.post_empty_file(repo_id, "/", page_name, username):
|
||||
return json_error(_(u'Failed to create home page. Please retry later'), 500)
|
||||
|
||||
next = reverse('personal_wiki', args=[])
|
||||
return HttpResponse(json.dumps({'href': next}), content_type=content_type)
|
||||
|
||||
@login_required
|
||||
def personal_wiki_page_new(request, page_name="home"):
|
||||
|
||||
if request.method == 'POST':
|
||||
page_name = request.POST.get('page_name', '')
|
||||
if not page_name:
|
||||
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
|
||||
page_name = clean_page_name(page_name)
|
||||
|
||||
repo = find_wiki_repo(request, group)
|
||||
if not repo:
|
||||
return render_error(request, _('Wiki is not found.'))
|
||||
|
||||
filename = page_name + ".md"
|
||||
filepath = "/" + page_name + ".md"
|
||||
|
||||
# check whether file exists
|
||||
if get_file_id_by_path(repo.id, filepath):
|
||||
return render_error(request, _('Page "%s" already exists.') % filename)
|
||||
|
||||
if not post_empty_file(repo.id, "/", filename, request.user.username):
|
||||
return render_error(request, _('Failed to create wiki page. Please retry later.'))
|
||||
|
||||
url = "%s?p=%s&from=wiki_page_new&gid=%s" % (
|
||||
reverse('file_edit', args=[repo.id]),
|
||||
urllib2.quote(filepath.encode('utf-8')), group.id)
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
@login_required
|
||||
def personal_wiki_page_edit(request, page_name="home"):
|
||||
try:
|
||||
repo = get_personal_wiki_repo(request.user.username)
|
||||
except WikiDoesNotExist:
|
||||
return render_error(request, _('Wiki is not found.'))
|
||||
|
||||
filepath = "/" + page_name + ".md"
|
||||
url = "%s?p=%s&from=personal_wiki_page_edit" % (
|
||||
reverse('file_edit', args=[repo.id]),
|
||||
urllib2.quote(filepath.encode('utf-8')))
|
||||
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
@login_required
|
||||
def personal_wiki_page_delete(request, page_name):
|
||||
try:
|
||||
repo = get_personal_wiki_repo(request.user.username)
|
||||
except WikiDoesNotExist:
|
||||
return render_error(request, _('Wiki is not found.'))
|
||||
|
||||
file_name = page_name + '.md'
|
||||
username = request.user.username
|
||||
if del_file(repo.id, '/', file_name, username):
|
||||
messages.success(request, 'Successfully deleted "%s".' % page_name)
|
||||
else:
|
||||
messages.error(request, 'Failed to delete "%s". Please retry later.' % page_name)
|
||||
|
||||
return HttpResponseRedirect(reverse('personal_wiki', args=[]))
|
4
wiki/__init__.py
Normal file
4
wiki/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from utils import get_personal_wiki_page, get_personal_wiki_repo, \
|
||||
convert_wiki_link, get_wiki_pages
|
37
wiki/forms.py
Normal file
37
wiki/forms.py
Normal file
@ -0,0 +1,37 @@
|
||||
# encoding: utf-8
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from seaserv import is_valid_filename
|
||||
|
||||
from utils import clean_page_name
|
||||
|
||||
class WikiCreateForm(forms.Form):
|
||||
"""
|
||||
A form used to create wiki.
|
||||
"""
|
||||
repo_name = forms.CharField(max_length=settings.MAX_FILE_NAME,
|
||||
error_messages={
|
||||
'required': _(u'Name can\'t be empty'),
|
||||
'max_length': _(u'Name is too long (maximum is 255 characters)')
|
||||
})
|
||||
repo_desc = forms.CharField(max_length=100, error_messages={
|
||||
'required': _(u'Description can\'t be empty'),
|
||||
'max_length': _(u'Description is too long (maximum is 100 characters)')
|
||||
})
|
||||
|
||||
def clean_repo_name(self):
|
||||
repo_name = self.cleaned_data['repo_name']
|
||||
if not is_valid_filename(repo_name):
|
||||
error_msg = _(u'"%s" is not a valid name') % repo_name
|
||||
raise forms.ValidationError(error_msg)
|
||||
else:
|
||||
return repo_name
|
||||
|
||||
|
||||
class WikiNewPageForm(forms.Form):
|
||||
page_name = forms.CharField(max_length=500)
|
||||
|
||||
def clean_page_name(self):
|
||||
page_name = self.cleaned_data['page_name']
|
25
wiki/models.py
Normal file
25
wiki/models.py
Normal file
@ -0,0 +1,25 @@
|
||||
from django.db import models
|
||||
|
||||
class WikiDoesNotExist(Exception):
|
||||
pass
|
||||
|
||||
class WikiPageMissing(Exception):
|
||||
pass
|
||||
|
||||
class PersonalWikiManager(models.Manager):
|
||||
def save_personal_wiki(self, username, repo_id):
|
||||
"""
|
||||
Create or update group wiki.
|
||||
"""
|
||||
try:
|
||||
wiki = self.get(username=username)
|
||||
wiki.repo_id = repo_id
|
||||
except self.model.DoesNotExist:
|
||||
wiki = self.model(username=username, repo_id=repo_id)
|
||||
wiki.save(using=self._db)
|
||||
return wiki
|
||||
|
||||
class PersonalWiki(models.Model):
|
||||
username = models.CharField(max_length=256, unique=True)
|
||||
repo_id = models.CharField(max_length=36)
|
||||
objects = PersonalWikiManager()
|
146
wiki/utils.py
Normal file
146
wiki/utils.py
Normal file
@ -0,0 +1,146 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import stat
|
||||
import urllib2
|
||||
|
||||
import seaserv
|
||||
from pysearpc import SearpcError
|
||||
from seahub.utils import EMPTY_SHA1
|
||||
from seahub.utils.repo import list_dir_by_path
|
||||
from seahub.utils.slugify import slugify
|
||||
from seahub.utils import render_error, render_permission_error, string2list, \
|
||||
gen_file_get_url, get_file_type_and_ext, \
|
||||
get_file_contributors
|
||||
|
||||
from models import WikiPageMissing, WikiDoesNotExist, \
|
||||
PersonalWiki
|
||||
|
||||
__all__ = ["get_wiki_dirent"]
|
||||
|
||||
|
||||
|
||||
SLUG_OK = "!@#$%^&()_+-,.;'"
|
||||
def normalize_page_name(page_name):
|
||||
# Remove special characters. Lower page name and replace spaces with '-'.
|
||||
return slugify(page_name, ok=SLUG_OK)
|
||||
|
||||
def clean_page_name(page_name):
|
||||
# Remove special characters. Do not lower page name and spaces are allowed.
|
||||
return slugify(page_name, ok=SLUG_OK, lower=False, spaces=True)
|
||||
|
||||
def get_wiki_dirent(repo_id, page_name):
|
||||
file_name = page_name + ".md"
|
||||
repo = seaserv.get_repo(repo_id)
|
||||
if not repo:
|
||||
raise WikiDoesNotExist
|
||||
cmmt = seaserv.get_commits(repo.id, 0, 1)[0]
|
||||
if cmmt is None:
|
||||
raise WikiPageMissing
|
||||
dirs = list_dir_by_path(cmmt, "/")
|
||||
if not dirs:
|
||||
raise WikiPageMissing
|
||||
else:
|
||||
for e in dirs:
|
||||
if stat.S_ISDIR(e.mode):
|
||||
continue # skip directories
|
||||
if normalize_page_name(file_name) == normalize_page_name(e.obj_name):
|
||||
return e
|
||||
raise WikiPageMissing
|
||||
|
||||
def get_file_url(repo, obj_id, file_name):
|
||||
repo_id = repo.id
|
||||
access_token = seaserv.seafserv_rpc.web_get_access_token(repo_id, obj_id,
|
||||
'view', '')
|
||||
url = gen_file_get_url(access_token, file_name)
|
||||
return url
|
||||
|
||||
def get_wiki_page(request, page_name):
|
||||
repo = find_wiki_repo(request, group)
|
||||
dirent = get_wiki_dirent(repo.id, page_name)
|
||||
if not dirent:
|
||||
raise WikiPageMissing
|
||||
url = get_file_url(repo, dirent.obj_id, dirent.obj_name)
|
||||
file_response = urllib2.urlopen(url)
|
||||
content = file_response.read()
|
||||
return content, repo.id, dirent
|
||||
|
||||
def get_personal_wiki_repo(username):
|
||||
try:
|
||||
wiki = PersonalWiki.objects.get(username=username)
|
||||
except PersonalWiki.DoesNotExist:
|
||||
raise WikiDoesNotExist
|
||||
repo = seaserv.get_repo(wiki.repo_id)
|
||||
if not repo:
|
||||
raise WikiDoesNotExist
|
||||
return repo
|
||||
|
||||
def get_personal_wiki_page(username, page_name):
|
||||
repo = get_personal_wiki_repo(username)
|
||||
dirent = get_wiki_dirent(repo.id, page_name)
|
||||
url = get_file_url(repo, dirent.obj_id, dirent.obj_name)
|
||||
file_response = urllib2.urlopen(url)
|
||||
content = file_response.read()
|
||||
return content, repo, dirent
|
||||
|
||||
def get_wiki_pages(repo):
|
||||
"""
|
||||
return pages in hashtable {normalized_name: page_name}
|
||||
"""
|
||||
dir_id = seaserv.seafserv_threaded_rpc.get_dir_id_by_path(repo.id, '/')
|
||||
dirs = seaserv.seafserv_threaded_rpc.list_dir(dir_id)
|
||||
pages = {}
|
||||
for e in dirs:
|
||||
if stat.S_ISDIR(e.mode):
|
||||
continue # skip directories
|
||||
name, ext = os.path.splitext(e.obj_name)
|
||||
if ext == '.md':
|
||||
key = normalize_page_name(name)
|
||||
pages[key] = name
|
||||
return pages
|
||||
|
||||
|
||||
def convert_wiki_link(content, url_prefix, repo_id, username):
|
||||
import re
|
||||
|
||||
def repl(matchobj):
|
||||
if matchobj.group(2): # return origin string in backquotes
|
||||
return matchobj.group(2)
|
||||
|
||||
page_name = matchobj.group(1).strip()
|
||||
filetype, fileext = get_file_type_and_ext(page_name)
|
||||
if fileext == '':
|
||||
# convert page_name that extension is missing to a markdown page
|
||||
dirent = get_wiki_dirent(repo_id, page_name)
|
||||
if dirent is not None:
|
||||
a_tag = "<a href='%s'>%s</a>"
|
||||
return a_tag % (url_prefix + '/' + normalize_page_name(page_name), page_name)
|
||||
else:
|
||||
a_tag = '''<a class="wiki-page-missing" href='%s'>%s</a>'''
|
||||
return a_tag % (url_prefix + '/' + page_name.replace('/', '-'), page_name)
|
||||
elif filetype == IMAGE:
|
||||
# load image to wiki page
|
||||
path = "/" + page_name
|
||||
filename = os.path.basename(path)
|
||||
obj_id = get_file_id_by_path(repo_id, path)
|
||||
if not obj_id:
|
||||
# Replace '/' in page_name to '-', since wiki name can not
|
||||
# contain '/'.
|
||||
return '''<a class="wiki-page-missing" href='%s'>%s</a>''' % \
|
||||
(url_prefix + '/' + page_name.replace('/', '-'), page_name)
|
||||
|
||||
token = seaserv.web_get_access_token(repo_id, obj_id, 'view', username)
|
||||
return '<img src="%s" alt="%s" />' % (gen_file_get_url(token, filename), filename)
|
||||
else:
|
||||
from base.templatetags.seahub_tags import file_icon_filter
|
||||
|
||||
# convert other types of filelinks to clickable links
|
||||
path = "/" + page_name
|
||||
icon = file_icon_filter(page_name)
|
||||
s = reverse('repo_view_file', args=[repo_id]) + \
|
||||
'?p=' + urllib2.quote(smart_str(path))
|
||||
a_tag = '''<img src="%simg/file/%s" alt="%s" class="vam" /> <a href='%s' target='_blank' class="vam">%s</a>'''
|
||||
return a_tag % (MEDIA_URL, icon, icon, s, page_name)
|
||||
|
||||
return re.sub(r'\[\[(.+)\]\]|(`.+`)', repl, content)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user