Add visibility management

This commit is contained in:
Gregory Soutade 2016-06-14 11:09:11 +02:00
parent 38be8017a0
commit 72c3a97ffa
12 changed files with 140 additions and 68 deletions

View File

@ -21,6 +21,7 @@
from django.forms import ModelForm
from django import forms
from denote.models import *
from datetime import datetime
class NoteForm(ModelForm):
text = forms.CharField(widget=forms.Textarea(attrs={'rows':'20', 'cols':'150'}))
@ -28,10 +29,13 @@ class NoteForm(ModelForm):
class Meta:
model = Note
exclude = ('author', 'transformed_text', 'long_summary', 'short_summary', 'created_date', 'modified_date', 'category', 'visibility')
exclude = ('author', 'transformed_text', 'long_summary', 'short_summary', 'created_date', 'modified_date', 'category')
class UserForm(ModelForm):
password = forms.CharField(required=False)
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
self.fields['first_name'].label = 'Name'
@ -39,4 +43,4 @@ class UserForm(ModelForm):
class Meta:
model = User
fields = ('first_name', 'username', 'password')
fields = ('first_name', 'username', 'password', 'home_notes_visibility')

View File

@ -33,6 +33,7 @@ from search import Search
class User(AbstractUser):
hidden_categories = models.TextField(blank=True)
home_notes_visibility = models.IntegerField(default=0, choices=[(0, 'private'), (1, 'registered'), (2, 'public')])
def getPreference(self, name):
if name == 'hidden_categories':
@ -58,6 +59,16 @@ class Category(models.Model):
name = models.CharField(max_length=50, unique=True, blank=False)
class Note(models.Model):
PRIVATE = 0
REGISTERED = 1
PUBLIC = 2
VISIBILITY = ((PRIVATE, 'Private'),
(REGISTERED, 'Registered'),
(PUBLIC, 'Public')
)
author = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
title = models.CharField(max_length=100, blank=False)
long_summary = models.CharField(max_length=255)
@ -66,7 +77,7 @@ class Note(models.Model):
transformed_text = models.TextField()
created_date = models.DateTimeField()
modified_date = models.DateTimeField()
visibility = models.IntegerField(default=0)
visibility = models.IntegerField(default=PRIVATE, choices=VISIBILITY)
category = models.ForeignKey(Category, null=True, on_delete=models.SET_NULL)
def _wrap(self, text, limit, max_limit):
@ -124,7 +135,10 @@ class Note(models.Model):
@receiver(post_save, sender=Note)
def post_save_note_signal(sender, **kwargs):
s = Search()
s.edit_note(kwargs['instance'].id)
if kwargs['created']:
s.index_note(kwargs['instance'].id)
else:
s.edit_note(kwargs['instance'].id)
@receiver(pre_delete, sender=Note)
def pre_delete_note_signal(sender, **kwargs):

View File

@ -111,7 +111,7 @@ div#categories div.name img
margin : 1em;
}
#main_panel .note .title a
.note .title a
{
color: black;
text-decoration: none;

View File

@ -96,6 +96,7 @@ function category_setup()
category = categories.childNodes[i];
if (category.nodeType != Node.ELEMENT_NODE) continue;
categoryId = category.getAttribute("category_id");
if (categoryId == null) continue;
hide = false;
for(a=0; a<hidden_categories.length;a++)
{

View File

@ -2,6 +2,10 @@
<head>
<title>Dénote{% if user.get_full_name|length != 0 %} - {{ user.get_full_name }}{% endif %}</title>
<link rel="icon" type="image/png" href="{{ STATIC_URL }}images/favicon.png" />
<script type="text/javascript">
var hidden_categories = null;
function get_csrf_token() { return '{{ csrf_token }}';}
</script>
{% block head %} {% endblock %}
<link href="{{ STATIC_URL }}css/denote.css" rel="stylesheet" type="text/css"/>
<link href="{{ STATIC_URL }}css/pygments.css" rel="stylesheet" type="text/css"/>
@ -9,8 +13,9 @@
</head>
<body onload="startup();">
<!-- Header -->
<div class="settings"><a href="/user/edit">Settings</a> <a href="/disconnect">Disconnect</a><br/>
<form action="/search">{% csrf_token %}<input name="text"/><input type="button" value="Search"/></form></div>
<div class="settings">{% if authenticated %}<a href="/user/edit">Settings</a> <a href="/disconnect">Disconnect</a><br/>
{% endif %}
<form action="/search" method="post">{% csrf_token %}<input name="text"/><input type="submit" value="Search"/></form></div>
<!-- Left panel -->
<div id="left_panel">
<a id="home_icon" href="/" alt="Home"><img src="{{ STATIC_URL }}images/home.png"/></a><br/><br/>

View File

@ -1,9 +1,8 @@
{% extends "base.html" %}
{% block head %}
<script type="text/javascript">
var hidden_categories = "{{ user.hidden_categories }}";
hidden_categories = "{{ user.hidden_categories }}";
hidden_categories = hidden_categories.split(",");
function get_csrf_token() { return '{{ csrf_token }}';}
</script>
{% endblock %}
{% block left %}

View File

@ -0,0 +1,20 @@
{% extends "base.html" %}
{% block left %}
{% for note in public_notes %}
<div id="categories">
<div class="note">
<a href="/note/{{ note.author.id}}/{{ note.id }}"><div class="title">{{ note.title }}</div></a>
<div class="date">{{ note.created_date }}</div>
<div class="summary">{{ note.short_summary }}</div>
</div>
</div>
{% endfor %}
{% endblock %}
{% block content %}
<div class="note">
<div id="title" class="title">{{ note.title }}</div>
<div id="transformed_content">{{ note.transformed_text|safe }}</div>
</div>
{% endblock %}

View File

@ -0,0 +1,26 @@
{% extends "base.html" %}
{% block left %}
{% for note in public_notes %}
<div id="categories">
<div class="note">
<a href="/note/{{ note.author.id}}/{{ note.id }}"><div class="title">{{ note.title }}</div></a>
<div class="date">{{ note.created_date }}</div>
<div class="summary">{{ note.short_summary }}</div>
</div>
</div>
{% endfor %}
{% endblock %}
{% block content %}
{% for note in notes %}
<div class="note">
<div class="title"><a href="/note/{{ note.author.id }}/{{ note.id }}">{{ note.title }}</a></div>
<div class="date">{{ note.modified_date }}</div>
<div class="summary">{{ note.long_summary }}</div>
</div>
{% endfor %}
{% if notes|length == 0 %}
<b>Any note</b>
{% endif %}
{% endblock %}

View File

@ -12,4 +12,7 @@
<div class="summary">{{ note.long_summary }}</div>
</div>
{% endfor %}
{% if notes|length == 0 %}
<b>Any note</b>
{% endif %}
{% endblock %}

View File

@ -2,12 +2,16 @@
{% block content %}
<div class="note">
{% if note != None %}
{% if note and note_form != None %}
<div id="title" class="title" ondblclick="edit_note();">{{ note.title }}</div>
{% if note.category != None %}
{% else %}
<div id="title" class="title">{{ note.title }}</div>
{% endif %}
{% if note and note.category != None %}
<div class="category">{{ note.category.name }}</div>
{% endif %}
<div id="transformed_content">{{ note.transformed_text|safe }}</div>
{% if note and note_form != None %}
<div class="edit_button"><input id="edit_button" type="button" value="Edit" onclick="edit_note();"/> <form id="form_delete" action="/note/{{ note.id }}" method="post">{% csrf_token %}<input type="submit" name="delete" value="Delete" onclick="return confirm('Do you really want to delete this note ?')"/></form></div>
<div id="div_edit">
<form id="form_edit" action="/note/{{ note.id }}" method="post">{% csrf_token %}
@ -21,54 +25,7 @@
<input type="submit" name="edit" value="Edit" />
<input type="button" value="Cancel" onclick="cancel_edit_note();"/>
</form>
<b>Markdown syntax</b><br /><br />
<table>
<tr>
<td class="markdown_help">
<pre style="display:inline">_italic_</pre> <span style="font-style:italic">italic</span><br/>
<pre style="display:inline">**bold**</pre> <span style="font-weight:bold">bold</span><br/>
<pre style="display:inline">~~line through~~</pre> <span style="text-decoration:line-through">line through</span><br/>
<pre style="display:inline">~underline~</pre> <span style="text-decoration:underline">underline</span><br/>
<pre style="display:inline">>Citation</pre><br/>
<pre>
* Unordered list
* Second element
</pre>
<ul>
<li>Unordered list
<li>Second element
</ul>
<pre>
1. Ordered list
1. Second element
</pre>
<ol>
<li>Ordered list
<li>Second element
</ol>
<pre style="display:inline">![Picture](https://bits.wikimedia.org/images/wikimedia-button.png)</pre><img src="https://bits.wikimedia.org/images/wikimedia-button.png" alt="Picture"/><br/>
<pre style="display:inline">#[Inline Picture](https://bits.wikimedia.org/images/wikimedia-button.png)</pre><img src="https://bits.wikimedia.org/images/wikimedia-button.png" alt="Picture"/><br/>
<pre style="display:inline">[Link](http://www.wikipedia.org)</pre> <a href="http://www.wikipedia.org">Link</a><br/><br/>
<pre>
Code : 4 whitespaces ahead
</pre>
</td>
<td>
<pre># Title # or
Title
=====</pre>
<h1>Title</h1>
<pre>## Sub title ## or
Sub title
---------</pre>
<h2>Sub title</h2>
<pre>### Sub sub title ###</pre>
<h3>Sub sub title</h3>
</td>
</tr>
</table>
</div>
{% else %}
{% else %}
<div class="form_add">
<form action="/note/add" method="post">{% csrf_token %}
{{ note_form.as_p }}
@ -81,7 +38,7 @@
<input type="submit" name="add" value="Add" />
<input type="submit" name="cancel" value="Cancel" />
</form>
</div>
{% endif %}
<b>Markdown syntax</b><br /><br />
<table>
<tr>
@ -131,6 +88,6 @@
</td>
</tr>
</table>
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -28,6 +28,7 @@ urlpatterns = patterns('',
url(r'^user/edit$','denote.views.edit_user', name='edit_user'),
url(r'^note/add$', 'denote.views.add_note', name='add_note'),
url(r'^note/(\d+)$', 'denote.views.note', name='note'),
url(r'^note/(\d+)/(\d+)$', 'denote.views.public_note', name='public_note'),
url(r'^category/edit/(\d)$','denote.views.edit_category', name='edit_category'),
url(r'^preferences$', 'denote.views.preferences', name='preferences'),
url(r'^search$', 'denote.views.search', name='search'),

View File

@ -21,7 +21,7 @@
import os
from datetime import datetime
from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.http import HttpResponseRedirect, HttpResponse, Http404, HttpResponseForbidden
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render
@ -115,6 +115,11 @@ def edit_user(request):
return render(request, 'edit_user.html', c)
def _prepare_note_context(user):
if not user.is_authenticated():
return {
'authenticated' : False,
}
categories = Category.objects.filter(author=user.id).order_by('name')
notes_by_category = []
need_refresh = False
@ -134,6 +139,7 @@ def _prepare_note_context(user):
context = {
'user': user,
'authenticated' : True,
'notes_by_category': notes_by_category,
'categories': categories,
'notes_without_category': notes_without_category,
@ -167,7 +173,8 @@ def add_note(request):
if 'cancel' in request.POST:
return HttpResponseRedirect('/')
else:
form = NoteForm()
note = Note(visibility=user.home_notes_visibility)
form = NoteForm(instance=note)
context = _prepare_note_context(user)
context['note_form'] = form
@ -201,6 +208,36 @@ def note(request, note_id):
return render(request, 'user_note.html', context)
def public_note(request, user_id, note_id):
user = request.user
try:
note = Note.objects.get(pk=note_id, author=user_id)
except:
raise Http404
if note is None:
raise Http404
if not user or not user.is_authenticated():
if note.visibility != Note.PUBLIC:
return HttpResponseForbidden()
else:
if note.visibility == Note.PRIVATE and\
user_id != user.id:
return HttpResponseForbidden()
if user.is_authenticated():
public_notes = Note.objects.filter(author=user_id, visibility__gte=Note.REGISTERED).order_by('-modified_date')
else:
public_notes = Note.objects.filter(author=user_id, visibility__gte=Note.PUBLIC).order_by('-modified_date')
context = _prepare_note_context(user)
context['note'] = note
context['public_notes'] = public_notes
return render(request, 'public_note.html', context)
@login_required
def edit_category(request, category_id):
user = request.user
@ -237,7 +274,6 @@ def preferences(request):
else:
raise Http404
@login_required
def search(request):
context = _prepare_note_context(request.user)
@ -251,11 +287,17 @@ def search(request):
s = Search()
note_list = s.search(text)
notes = Note.objects.filter(pk__in=note_list, author=request.user)
context['notes'] = notes
context['note_form'] = NoteForm()
if request.user.is_authenticated():
notes = Note.objects.filter(pk__in=note_list, author=request.user)
return render(request, 'user_index.html', context)
context['notes'] = notes
context['note_form'] = NoteForm()
return render(request, 'user_index.html', context)
else:
notes = Note.objects.filter(pk__in=note_list, visibility__gte=Note.PUBLIC)
context['notes'] = notes
return render(request, 'public_notes.html', context)
@login_required
def generate_search_index(request):