mirror of
https://github.com/DarrenOfficial/dpaste.git
synced 2024-11-23 11:56:36 +11:00
POST based snippet delete
This commit is contained in:
parent
38dd6f5c89
commit
8d10c0bd1e
8 changed files with 172 additions and 117 deletions
|
@ -11,7 +11,6 @@ body[data-code-snippet] { background-color: $codeBgColor; }
|
|||
body[data-platform=win] .platform-mac { display: none; }
|
||||
body[data-platform=mac] .platform-win { display: none; }
|
||||
|
||||
|
||||
.btn {
|
||||
padding: 6px 0;
|
||||
position: relative;
|
||||
|
@ -45,3 +44,34 @@ body[data-platform=mac] .platform-win { display: none; }
|
|||
top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-modal {
|
||||
@include colored-links;
|
||||
background-color: $confirmBgColor;
|
||||
color: $confirmTextColor;
|
||||
|
||||
// Hidden by default
|
||||
overflow: hidden;
|
||||
max-height: 0;
|
||||
|
||||
// Foldout animation
|
||||
transition: max-height .15s ease-in;
|
||||
|
||||
form {
|
||||
display: block;
|
||||
padding: 20px $boxPadding;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 6px 15px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.no {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&:target {
|
||||
max-height: 80px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,3 +5,17 @@
|
|||
border-right: 2px dotted $color;
|
||||
margin: 0 ($margin+2px) 0 $margin;
|
||||
}
|
||||
|
||||
|
||||
@mixin colored-links() {
|
||||
a:link, a:visited {
|
||||
color: $linkColor;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: lighten($linkColor, 30%);
|
||||
}
|
||||
|
||||
a:hover, a:active {
|
||||
color: $hoverColor;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,14 +29,5 @@ article {
|
|||
font-weight: $baseFontDemiBold;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
color: $linkColor;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: lighten($linkColor, 30%);
|
||||
}
|
||||
|
||||
a:hover, a:active {
|
||||
color: $hoverColor;
|
||||
text-decoration: underline;
|
||||
}
|
||||
@include colored-links;
|
||||
}
|
||||
|
|
|
@ -33,15 +33,8 @@
|
|||
</li>
|
||||
<li class="sep"></li>
|
||||
<li>
|
||||
<a href="{% url "snippet_delete" snippet.secret_id %}"
|
||||
onclick="return confirm('{% trans "Are you sure you want to delete this snippet?" %}');">{% trans "Delete Now" %}</a>
|
||||
<a href="#delete">{% trans "Delete Now" %}</a>
|
||||
</li>
|
||||
<!--
|
||||
{% if snippet.parent %}
|
||||
<li><a href="#snippet-diff">{% trans "Compare with previous Snippet" %}</a></li>
|
||||
{% endif %}
|
||||
-->
|
||||
|
||||
{% if snippet.expire_type != 3 %}
|
||||
<li><a href="{% url "snippet_details_raw" snippet.secret_id %}">{% trans "View Raw" %}</a></li>
|
||||
{% endif %}
|
||||
|
@ -53,6 +46,15 @@
|
|||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<div id="delete" class="confirm-modal">
|
||||
<form method="POST" action="">
|
||||
{% csrf_token %}
|
||||
{% trans "Are you sure to delete this snippet?" %}
|
||||
<button class="btn" name="delete" value="1" type="submit">{% trans "Yes, Delete" %}</button>
|
||||
<a href="#" class="no">{% trans "No, don't delete" %}</a>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block page %}
|
||||
|
|
|
@ -11,18 +11,28 @@
|
|||
<li>{% trans "Snippet History" %}</li>
|
||||
{% if snippet_list %}
|
||||
<li class="sep"></li>
|
||||
<li><a href="#delete">{% trans "Delete all Snippets" %}</a></li>
|
||||
<li>
|
||||
<a href="?delete-all"
|
||||
onclick="return confirm('{% trans "Are you sure you want to delete all snippets?" %}');">{% trans "Delete all Snippets" %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<label for="wordwrap">
|
||||
{# Wordwrap is enabled by default for all lexer in the history #}
|
||||
<label for="wordwrap">
|
||||
<input type="checkbox" id="wordwrap" checked> Wordwrap
|
||||
</label>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<div id="delete" class="confirm-modal">
|
||||
<form method="POST" action="">
|
||||
{% csrf_token %}
|
||||
{% blocktrans count snippet_list|length as count %}
|
||||
Do you really want to delete the snippet below?
|
||||
{% plural %}
|
||||
Do you really want to delete the {{ count }} snippets below?
|
||||
{% endblocktrans %}
|
||||
<button class="btn" name="delete" value="1" type="submit">{% trans "Yes, Delete All" %}</button>
|
||||
<a href="#" class="no">{% trans "No, don't delete" %}</a>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block page %}
|
||||
|
|
|
@ -8,14 +8,12 @@ from .. import views
|
|||
L = getattr(settings, 'DPASTE_SLUG_LENGTH', 4)
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^about/$', views.AboutView.as_view(), name='dpaste_about'),
|
||||
|
||||
url(r'^$', views.SnippetView.as_view(), name='snippet_new'),
|
||||
url(r'^diff/$', views.SnippetDiffView.as_view(), name='snippet_diff'),
|
||||
url(r'^about/$', views.AboutView.as_view(), name='dpaste_about'),
|
||||
url(r'^history/$', views.SnippetHistory.as_view(), name='snippet_history'),
|
||||
url(r'^delete/$', views.SnippetDeleteView.as_view(), name='snippet_delete'),
|
||||
|
||||
url(r'^(?P<snippet_id>[a-zA-Z0-9]{%d,})/?$' % L, views.SnippetDetailView.as_view(), name='snippet_details'),
|
||||
url(r'^(?P<snippet_id>[a-zA-Z0-9]{%d,})/delete/$' % L, views.SnippetDeleteView.as_view(), name='snippet_delete'),
|
||||
url(r'^(?P<snippet_id>[a-zA-Z0-9]{%d,})/raw/?$' % L, views.SnippetRawView.as_view(), name='snippet_details_raw'),
|
||||
url(r'^(?P<snippet_id>[a-zA-Z0-9]{%d,})/?$' % L,
|
||||
views.SnippetDetailView.as_view(), name='snippet_details'),
|
||||
url(r'^(?P<snippet_id>[a-zA-Z0-9]{%d,})/raw/?$' % L,
|
||||
views.SnippetRawView.as_view(), name='snippet_details_raw'),
|
||||
]
|
||||
|
|
180
dpaste/views.py
180
dpaste/views.py
|
@ -66,6 +66,24 @@ class SnippetDetailView(SnippetView, DetailView):
|
|||
slug_url_kwarg = 'snippet_id'
|
||||
slug_field = 'secret_id'
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
"""
|
||||
Delete a snippet. This is allowed by anybody as long as he knows the
|
||||
snippet id. I got too many manual requests to do this, mostly for legal
|
||||
reasons and the chance to abuse this is not given anyway, since snippets
|
||||
always expire.
|
||||
"""
|
||||
if 'delete' in self.request.POST:
|
||||
snippet = get_object_or_404(Snippet, secret_id=self.kwargs['snippet_id'])
|
||||
snippet.delete()
|
||||
|
||||
# Append `#` so #delete goes away in Firefox
|
||||
url = '{0}#'.format(reverse('snippet_new'))
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
return super(SnippetDetailView, self).post(*args, **kwargs)
|
||||
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
snippet = self.get_object()
|
||||
|
||||
|
@ -101,6 +119,7 @@ class SnippetDetailView(SnippetView, DetailView):
|
|||
})
|
||||
return ctx
|
||||
|
||||
|
||||
class SnippetRawView(SnippetDetailView):
|
||||
"""
|
||||
Display the raw content of a snippet
|
||||
|
@ -113,22 +132,6 @@ class SnippetRawView(SnippetDetailView):
|
|||
return response
|
||||
|
||||
|
||||
class SnippetDeleteView(View):
|
||||
"""
|
||||
Delete a snippet. This is allowed by anybody as long as he knows the
|
||||
snippet id. I got too many manual requests to do this, mostly for legal
|
||||
reasons and the chance to abuse this is not given anyway, since snippets
|
||||
always expire.
|
||||
"""
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
snippet_id = self.kwargs.get('snippet_id') or request.POST.get('snippet_id')
|
||||
if not snippet_id:
|
||||
raise Http404('No snippet id given')
|
||||
snippet = get_object_or_404(Snippet, secret_id=snippet_id)
|
||||
snippet.delete()
|
||||
return HttpResponseRedirect(reverse('snippet_new'))
|
||||
|
||||
|
||||
class SnippetHistory(TemplateView):
|
||||
"""
|
||||
Display the last `n` snippets created by this user (and saved in his
|
||||
|
@ -136,85 +139,92 @@ class SnippetHistory(TemplateView):
|
|||
"""
|
||||
template_name = 'dpaste/history.html'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
snippet_id_list = request.session.get('snippet_list', [])
|
||||
self.snippet_list = Snippet.objects.filter(pk__in=snippet_id_list)
|
||||
def get_user_snippets(self):
|
||||
snippet_id_list = self.request.session.get('snippet_list', [])
|
||||
return Snippet.objects.filter(pk__in=snippet_id_list)
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
"""
|
||||
Delete all user snippets at once.
|
||||
"""
|
||||
if 'delete' in self.request.POST:
|
||||
self.get_user_snippets().delete()
|
||||
|
||||
# Append `#` so #delete goes away in Firefox
|
||||
url = '{0}#'.format(reverse('snippet_history'))
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
if 'delete-all' in request.GET:
|
||||
self.snippet_list.delete()
|
||||
return HttpResponseRedirect(reverse('snippet_history'))
|
||||
return super(SnippetHistory, self).get(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(SnippetHistory, self).get_context_data(**kwargs)
|
||||
ctx.update({
|
||||
'snippets_max': getattr(settings, 'DPASTE_MAX_SNIPPETS_PER_USER', 10),
|
||||
'snippet_list': self.snippet_list,
|
||||
'snippet_list': self.get_user_snippets(),
|
||||
})
|
||||
return ctx
|
||||
|
||||
|
||||
class SnippetDiffView(TemplateView):
|
||||
"""
|
||||
Display a diff between two given snippet secret ids.
|
||||
"""
|
||||
template_name = 'dpaste/includes/diff.html'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
Some validation around input files we will compare later.
|
||||
"""
|
||||
if request.GET.get('a') and request.GET.get('a').isdigit() \
|
||||
and request.GET.get('b') and request.GET.get('b').isdigit():
|
||||
try:
|
||||
self.fileA = Snippet.objects.get(pk=int(request.GET.get('a')))
|
||||
self.fileB = Snippet.objects.get(pk=int(request.GET.get('b')))
|
||||
except ObjectDoesNotExist:
|
||||
return HttpResponseBadRequest(u'Selected file(s) does not exist.')
|
||||
else:
|
||||
return HttpResponseBadRequest(u'You must select two snippets.')
|
||||
|
||||
return super(SnippetDiffView, self).get(request, *args, **kwargs)
|
||||
|
||||
def get_diff(self):
|
||||
class DiffText(object):
|
||||
pass
|
||||
|
||||
diff = DiffText()
|
||||
|
||||
if self.fileA.content != self.fileB.content:
|
||||
d = difflib.unified_diff(
|
||||
self.fileA.content.splitlines(),
|
||||
self.fileB.content.splitlines(),
|
||||
'Original',
|
||||
'Current',
|
||||
lineterm=''
|
||||
)
|
||||
|
||||
diff.content = '\n'.join(d).strip()
|
||||
diff.lexer = 'diff'
|
||||
else:
|
||||
diff.content = force_text(_(u'No changes were made between this two files.'))
|
||||
diff.lexer = 'text'
|
||||
|
||||
return diff
|
||||
|
||||
def highlight_snippet(self, content):
|
||||
h = highlight.pygmentize(content, 'diff')
|
||||
h = h.replace(u'\t', ' ')
|
||||
return h
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
diff = self.get_diff()
|
||||
highlighted = self.highlight_snippet(diff.content)
|
||||
ctx = super(SnippetDiffView, self).get_context_data(**kwargs)
|
||||
ctx.update({
|
||||
'snippet': diff,
|
||||
'highlighted': highlighted.splitlines(),
|
||||
'fileA': self.fileA,
|
||||
'fileB': self.fileB,
|
||||
})
|
||||
return ctx
|
||||
# class SnippetDiffView(TemplateView):
|
||||
# """
|
||||
# Display a diff between two given snippet secret ids.
|
||||
# """
|
||||
# template_name = 'dpaste/includes/diff.html'
|
||||
#
|
||||
# def get(self, request, *args, **kwargs):
|
||||
# """
|
||||
# Some validation around input files we will compare later.
|
||||
# """
|
||||
# if request.GET.get('a') and request.GET.get('a').isdigit() \
|
||||
# and request.GET.get('b') and request.GET.get('b').isdigit():
|
||||
# try:
|
||||
# self.fileA = Snippet.objects.get(pk=int(request.GET.get('a')))
|
||||
# self.fileB = Snippet.objects.get(pk=int(request.GET.get('b')))
|
||||
# except ObjectDoesNotExist:
|
||||
# return HttpResponseBadRequest(u'Selected file(s) does not exist.')
|
||||
# else:
|
||||
# return HttpResponseBadRequest(u'You must select two snippets.')
|
||||
#
|
||||
# return super(SnippetDiffView, self).get(request, *args, **kwargs)
|
||||
#
|
||||
# def get_diff(self):
|
||||
# class DiffText(object):
|
||||
# pass
|
||||
#
|
||||
# diff = DiffText()
|
||||
#
|
||||
# if self.fileA.content != self.fileB.content:
|
||||
# d = difflib.unified_diff(
|
||||
# self.fileA.content.splitlines(),
|
||||
# self.fileB.content.splitlines(),
|
||||
# 'Original',
|
||||
# 'Current',
|
||||
# lineterm=''
|
||||
# )
|
||||
#
|
||||
# diff.content = '\n'.join(d).strip()
|
||||
# diff.lexer = 'diff'
|
||||
# else:
|
||||
# diff.content = force_text(_(u'No changes were made between this two files.'))
|
||||
# diff.lexer = 'text'
|
||||
#
|
||||
# return diff
|
||||
#
|
||||
# def highlight_snippet(self, content):
|
||||
# h = highlight.pygmentize(content, 'diff')
|
||||
# h = h.replace(u'\t', ' ')
|
||||
# return h
|
||||
#
|
||||
# def get_context_data(self, **kwargs):
|
||||
# diff = self.get_diff()
|
||||
# highlighted = self.highlight_snippet(diff.content)
|
||||
# ctx = super(SnippetDiffView, self).get_context_data(**kwargs)
|
||||
# ctx.update({
|
||||
# 'snippet': diff,
|
||||
# 'highlighted': highlighted.splitlines(),
|
||||
# 'fileA': self.fileA,
|
||||
# 'fileB': self.fileB,
|
||||
# })
|
||||
# return ctx
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue