Commit 39d8d0d95fe1e71212393d1d6900cdf912f2d041

Authored by Marco
2 parents 9c56645c f9159f05

Merge branch 'master' of https://github.com/interlegis/colab

requirements.txt
... ... @@ -48,3 +48,6 @@ transliterate==1.5
48 48 # Diazo
49 49 #diazo
50 50 git+https://github.com/plone/diazo@44ca0da7de5a7ee5d4085c7344701b9cfecfb419
  51 +
  52 +# Dpaste
  53 +git+https://github.com/interlegis/dpaste
... ...
src/colab/custom_settings.py
... ... @@ -107,6 +107,8 @@ INSTALLED_APPS = INSTALLED_APPS + (
107 107 'haystack',
108 108 'hitcounter',
109 109 'i18n_model',
  110 + 'mptt',
  111 + 'dpaste',
110 112  
111 113 # Own apps
112 114 'super_archives',
... ... @@ -207,7 +209,6 @@ TEMPLATE_CONTEXT_PROCESSORS = (
207 209 'django.core.context_processors.tz',
208 210 'django.contrib.messages.context_processors.messages',
209 211 'django.core.context_processors.request',
210   - 'django_browserid.context_processors.browserid',
211 212 'django_mobile.context_processors.is_mobile',
212 213 'super_archives.context_processors.mailarchive',
213 214 'home.context_processors.robots',
... ... @@ -303,6 +304,18 @@ CONVERSEJS_SHOW_ONLY_ONLINE_USERS = True
303 304 TASTYPIE_DEFAULT_FORMATS = ['json', ]
304 305  
305 306  
  307 +# Dpaste settings
  308 +DPASTE_EXPIRE_CHOICES = (
  309 + ('onetime', _(u'One Time Snippet')),
  310 + (3600, _(u'In one hour')),
  311 + (3600 * 24 * 7, _(u'In one week')),
  312 + (3600 * 24 * 30, _(u'In one month')),
  313 + ('never', _(u'Never')),
  314 +)
  315 +DPASTE_EXPIRE_DEFAULT = DPASTE_EXPIRE_CHOICES[4][0]
  316 +DPASTE_DEFAULT_GIST_DESCRIPTION = 'Gist created on Colab'
  317 +DPASTE_DEFAULT_GIST_NAME = 'colab_paste'
  318 +
306 319 try:
307 320 from local_settings import *
308 321 except ImportError:
... ...
src/colab/urls.py
... ... @@ -28,7 +28,7 @@ urlpatterns = patterns('',
28 28  
29 29 url(r'^planet/', include('feedzilla.urls')),
30 30  
31   - url(r'', include('django_browserid.urls')),
  31 + url(r'paste/', include('dpaste.urls.dpaste')),
32 32  
33 33 # Uncomment the next line to enable the admin:
34 34 url(r'^colab/admin/', include(admin.site.urls)),
... ...
src/static/dpaste/css/theme.css 0 → 100644
... ... @@ -0,0 +1,212 @@
  1 +
  2 +.shortcut {
  3 + color: #AAA;
  4 + font-size: 13px;
  5 + font-weight: 300;
  6 + margin-left: 15px;
  7 +}
  8 +
  9 +.form-horizontal .form-group {
  10 + margin: 0 0 20px 0;
  11 +}
  12 +
  13 +#id_content{
  14 + width: 100%;
  15 + font-family: monospace;
  16 + font-size: 14px;
  17 + line-height: 16px;
  18 +}
  19 +
  20 +/* ----------------------------------------------------------------------------
  21 + Snippet Details
  22 +---------------------------------------------------------------------------- */
  23 +#snippet-diff {
  24 + display: none;
  25 +}
  26 +.snippet-options{
  27 + margin-bottom: 20px;
  28 +}
  29 +
  30 +.snippet-reply {
  31 + margin-top: 30px;
  32 +}
  33 +
  34 +.snippet-reply-hidden {
  35 + opacity: 0.3;
  36 +}
  37 +
  38 +.snippet-reply-hidden,
  39 +.snippet-reply-hidden *{
  40 + cursor: pointer;
  41 +}
  42 +
  43 +.snippet-diff-form {
  44 +}
  45 +
  46 +.snippet-rendered {
  47 + color: #666;
  48 + font-size: 16px;
  49 + line-height: 24px;
  50 + max-width: 620px;
  51 + font-family: Helvetica, FreeSerif, serif;
  52 + font-weight: 300;
  53 +}
  54 +.diff-form {
  55 +/* margin-bottom: 10px;*/
  56 +}
  57 +
  58 +#diff {
  59 + margin-bottom: 10px;
  60 +/* display: none;*/
  61 +}
  62 +
  63 +.tree{
  64 + width: 100%;
  65 + line-height: 1.8em;
  66 +}
  67 +
  68 +.tree ul,
  69 +.tree ul li{
  70 + margin: 0;
  71 + padding: 0;
  72 + list-style: none;
  73 +}
  74 +
  75 +.tree ul li{
  76 + color: #ccc;
  77 + clear: both;
  78 +}
  79 +
  80 +.tree ul li div{
  81 + border-bottom: 1px solid #EEE;
  82 +}
  83 +
  84 +.tree strong{
  85 + color: #111;
  86 + font-weight: normal;
  87 +}
  88 +
  89 +.tree ul li li{
  90 + padding-left: 0;
  91 + margin-left: 15px;
  92 + color: #ccc;
  93 + list-style: circle;
  94 +}
  95 +
  96 +/* ----------------------------------------------------------------------------
  97 + .code
  98 +---------------------------------------------------------------------------- */
  99 +
  100 +.code {
  101 + width: 100%;
  102 + background: #232829;
  103 + color: #f8f8f2;
  104 + padding: 20px 30px !important;
  105 + border-radius: 0;
  106 + padding: 20px 30px;
  107 + font-family: Monaco,Menlo,Consolas,"Courier New",monospace;
  108 +}
  109 +
  110 +.code.wordwrap {
  111 + overflow: auto;
  112 + white-space: nowrap;
  113 +}
  114 +
  115 +.code ol {
  116 + margin: 0 0 0 45px;
  117 +}
  118 +
  119 +.code ol li {
  120 + color: #aaa;
  121 + font-size: 12px;
  122 + line-height: 21px;
  123 + cursor: pointer;
  124 + padding-left: 5px;
  125 +}
  126 +
  127 +.code ol li.marked {
  128 + color: #f4e009;
  129 + background-color: #4f4800;
  130 + margin-right: -30px;
  131 + padding-right: 30px;
  132 +}
  133 +
  134 +/* ----------------------------------------------------------------------------
  135 + Pygments
  136 +---------------------------------------------------------------------------- */
  137 +
  138 +.code .gd { color: #FF494F; display: block; }
  139 +.code .gi { color: #53C64A; display: block; }
  140 +
  141 +.code .hll { background-color: #49483e }
  142 +.code .c { color: #75715e } /* Comment */
  143 +.code .err { color: #960050; background-color: #1e0010 } /* Error */
  144 +.code .k { color: #66d9ef } /* Keyword */
  145 +.code .l { color: #ae81ff } /* Literal */
  146 +.code .n { color: #f8f8f2 } /* Name */
  147 +.code .o { color: #f92672 } /* Operator */
  148 +.code .p { color: #f8f8f2 } /* Punctuation */
  149 +.code .cm { color: #75715e } /* Comment.Multiline */
  150 +.code .cp { color: #75715e } /* Comment..codeproc */
  151 +.code .c1 { color: #75715e } /* Comment.Single */
  152 +.code .cs { color: #75715e } /* Comment.Special */
  153 +.code .ge { font-style: italic } /* Generic.Emph */
  154 +.code .gs { font-weight: bold } /* Generic.Strong */
  155 +.code .kc { color: #66d9ef } /* Keyword.Constant */
  156 +.code .kd { color: #66d9ef } /* Keyword.Declaration */
  157 +.code .kn { color: #f92672 } /* Keyword.Namespace */
  158 +.code .kp { color: #66d9ef } /* Keyword.Pseudo */
  159 +.code .kr { color: #66d9ef } /* Keyword.Reserved */
  160 +.code .kt { color: #66d9ef } /* Keyword.Type */
  161 +.code .ld { color: #e6db74 } /* Literal.Date */
  162 +.code .m { color: #ae81ff } /* Literal.Number */
  163 +.code .s { color: #e6db74 } /* Literal.String */
  164 +.code .na { color: #a6e22e } /* Name.Attribute */
  165 +.code .nb { color: #f8f8f2 } /* Name.Builtin */
  166 +.code .nc { color: #a6e22e } /* Name.Class */
  167 +.code .no { color: #66d9ef } /* Name.Constant */
  168 +.code .nd { color: #a6e22e } /* Name.Decorator */
  169 +.code .ni { color: #f8f8f2 } /* Name.Entity */
  170 +.code .ne { color: #a6e22e } /* Name.Exception */
  171 +.code .nf { color: #a6e22e } /* Name.Function */
  172 +.code .nl { color: #f8f8f2 } /* Name.Label */
  173 +.code .nn { color: #f8f8f2 } /* Name.Namespace */
  174 +.code .nx { color: #a6e22e } /* Name.Other */
  175 +.code .py { color: #f8f8f2 } /* Name.Property */
  176 +.code .nt { color: #f92672 } /* Name.Tag */
  177 +.code .nv { color: #f8f8f2 } /* Name.Variable */
  178 +.code .ow { color: #f92672 } /* Operator.Word */
  179 +.code .w { color: #f8f8f2 } /* Text.Whitespace */
  180 +.code .mf { color: #ae81ff } /* Literal.Number.Float */
  181 +.code .mh { color: #ae81ff } /* Literal.Number.Hex */
  182 +.code .mi { color: #ae81ff } /* Literal.Number.Integer */
  183 +.code .mo { color: #ae81ff } /* Literal.Number.Oct */
  184 +.code .sb { color: #e6db74 } /* Literal.String.Backtick */
  185 +.code .sc { color: #e6db74 } /* Literal.String.Char */
  186 +.code .sd { color: #e6db74 } /* Literal.String.Doc */
  187 +.code .s2 { color: #e6db74 } /* Literal.String.Double */
  188 +.code .se { color: #ae81ff } /* Literal.String.Escape */
  189 +.code .sh { color: #e6db74 } /* Literal.String.Heredoc */
  190 +.code .si { color: #e6db74 } /* Literal.String.Interpol */
  191 +.code .sx { color: #e6db74 } /* Literal.String.Other */
  192 +.code .sr { color: #e6db74 } /* Literal.String.Regex */
  193 +.code .s1 { color: #e6db74 } /* Literal.String.Single */
  194 +.code .ss { color: #e6db74 } /* Literal.String.Symbol */
  195 +.code .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
  196 +.code .vc { color: #f8f8f2 } /* Name.Variable.Class */
  197 +.code .vg { color: #f8f8f2 } /* Name.Variable.Global */
  198 +.code .vi { color: #f8f8f2 } /* Name.Variable.Instance */
  199 +.code .il { color: #ae81ff } /* Literal.Number.Integer.Long */
  200 +
  201 +
  202 +/* ----------------------------------------------------------------------------
  203 + Mobile
  204 +---------------------------------------------------------------------------- */
  205 +
  206 +@media (max-width: 580px) {
  207 + .form-options-expire {
  208 + float: left;
  209 + clear: left;
  210 + margin-top: 10px;
  211 + }
  212 +}
... ...
src/templates/base.html
... ... @@ -184,5 +184,7 @@
184 184  
185 185 {% include "tz/set_utc_offset.html" %}
186 186 {% browserid_js %}
  187 +
  188 + {% block footer_js %}{% endblock %}
187 189 </body>
188 190 </html>
... ...
src/templates/dpaste/base.html 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +{% extends 'base.html' %}
  2 +
  3 +{% block head_css %}
  4 +<link rel="stylesheet" href="{{ STATIC_URL }}dpaste/css/theme.css"
  5 + type="text/css" media="screen" />
  6 +{% endblock %}
  7 +
  8 +{% block header %}
  9 +<h2>Paste</h2>
  10 +{% endblock %}
  11 +
  12 +{% block main-content %}
  13 +{% block page %}{% endblock %}
  14 +{% endblock %}
  15 +
  16 +{% block footer_js %}{% endblock %}
... ...
src/templates/dpaste/snippet_details.html 0 → 100644
... ... @@ -0,0 +1,207 @@
  1 +{% extends "dpaste/base.html" %}
  2 +
  3 +{% load mptt_tags %}
  4 +{% load i18n %}
  5 +{% load dpaste_tags %}
  6 +
  7 +{% block page %}
  8 +
  9 +{# Snippet options #}
  10 +
  11 +
  12 +<div id="snippet-diff" class="row">
  13 + <div class="col-md-10">
  14 + <div id="diff" style="display:none;"></div>
  15 + </div>
  16 + <div id="snippet-diff-form" class="col-md-2">
  17 + <form method="get" id="diffform" action="{% url "snippet_diff" %}">
  18 + {% csrf_token %}
  19 + <div class="form-group tree">
  20 + {% for tree_item,structure in tree|tree_info %}
  21 + {% if structure.new_level %}<ul><li>{% else %}</li><li>{% endif %}
  22 + <div>
  23 + <span class="pull-right">
  24 + <input type="radio" name="a" value="{{ tree_item.id }}" {% ifequal tree_item.id snippet.parent_id %}checked="checked"{% endifequal %}>
  25 + <input type="radio" name="b" value="{{ tree_item.id }}" {% ifequal snippet tree_item %}checked="checked"{% endifequal %}>
  26 + </span>
  27 + {% ifequal snippet tree_item %}
  28 + <strong>#{{ tree_item.id }}</strong>
  29 + {% else %}
  30 + <a href="{{ tree_item.get_absolute_url }}">#{{ tree_item.id }}</a>
  31 + {% endifequal %}
  32 + </div>
  33 + {% for level in structure.closed_levels %}</li></ul>{% endfor %}
  34 + {% endfor %}
  35 + </div>
  36 + <div class="form-group pull-right">
  37 + <button type="submit" class="btn btn-default">{% trans "Compare" %}</button>
  38 + </div>
  39 + </form>
  40 + </div>
  41 +</div>
  42 +
  43 +
  44 +<div class="btn-group btn-group-sm snippet-options">
  45 + <a href="#" class="btn btn-default disabled">
  46 + {% if snippet.expire_type == 1 %}
  47 + {% blocktrans with date=snippet.expires|timeuntil %}Expires in: {{ date }}{% endblocktrans %}
  48 + {% elif snippet.expire_type == 2 %}
  49 + {% trans "Snippet never expires" %}
  50 + {% elif snippet.expire_type == 3 %}
  51 + {% trans "One-time snippet" %}
  52 + {% endif %}
  53 + </a>
  54 +
  55 + {% if snippet.pk|in_list:request.session.snippet_list %}
  56 + <a href="{% url "snippet_delete" snippet.secret_id %}" class="btn btn-default" onclick="return confirm('{% trans "Really delete this snippet?" %}');">
  57 + <span class="glyphicon glyphicon-trash"></span>
  58 + {% trans "Delete Now" %}
  59 + </a>
  60 + {% endif %}
  61 +
  62 + {% if not snippet.is_single %}
  63 + <a href="#snippet-diff" class="btn btn-default snippet-diff-trigger" title="{% trans "Compare Snippets" %}">
  64 + <span class="glyphicon glyphicon-search"></span>
  65 + {% trans "Compare Snippets" %}
  66 + </a>
  67 + {% endif %}
  68 +
  69 + <a href="{% url "snippet_details_raw" snippet.secret_id %}" class="btn btn-default" title="{% trans "View Raw" %}">
  70 + <span class="glyphicon glyphicon-align-left"></span>
  71 + {% trans "View Raw" %}
  72 + </a>
  73 + <a href="{% url "snippet_gist" snippet.secret_id %}" class="btn btn-default" rel="nofollow" title="Create a secret Gist">
  74 + <span class="glyphicon glyphicon-share"></span>
  75 + </i> {% trans "Gist" %}
  76 + </a>
  77 + <a href="/pastebin" class="btn btn-primary">
  78 + New snippet
  79 + <span class="glyphicon glyphicon-arrow-right"></span>
  80 + </a>
  81 +</div>
  82 +
  83 +
  84 + {% if snippet.expire_type == 3 %}
  85 + <div class="alert alert-warning alert-dismissable">
  86 + <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
  87 +
  88 + {% trans "This is a one-time snippet." %}
  89 + {% if snippet.remaining_views > 1 %}
  90 + {% trans "It will automatically get deleted after {{ remaining }} further views." %}
  91 + {% elif snippet.remaining_views == 1 %}
  92 + {% trans "It will automatically get deleted after the next view." %}
  93 + {% else %}
  94 + {% trans "It cannot be viewed again." %}
  95 + {% endif %}
  96 + </div>
  97 + {% endif %}
  98 +
  99 + {% if snippet.lexer == 'text' %}
  100 + <div class="snippet-rendered">
  101 + {{ snippet.content|linebreaksbr }}
  102 + </div>
  103 + {% else %}
  104 + {% include "dpaste/snippet_pre.html" %}
  105 + {% endif %}
  106 +
  107 + {% if not snippet.expire_type == 3 %}
  108 + <div class="snippet-reply snippet-reply-hidden">
  109 + <h3>{% trans "Reply to this snippet" %} &rarr;</h3>
  110 + {% include "dpaste/snippet_form.html" %}
  111 + </div>
  112 + {% endif %}
  113 +
  114 +
  115 +
  116 +{% block footer_js %}
  117 +<script>
  118 +
  119 +$(document).ready(function() {
  120 + $('.snippet-reply-hidden').click(function(e) {
  121 + $(this).removeClass('snippet-reply-hidden');
  122 + });
  123 +
  124 + var diffReq;
  125 +
  126 + $('.snippet-diff-trigger').click(function(event) {
  127 + $('#snippet-diff form').submit();
  128 + $('#snippet-diff').show();
  129 + event.preventDefault();
  130 + });
  131 +
  132 +
  133 + $('#diffform').submit(function() {
  134 + var a = $('input[name="a"]:checked').val(),
  135 + b = $('input[name="b"]:checked').val();
  136 +
  137 + window.location.hash = 'D' + a + ',' + b;
  138 +
  139 + // Cancel previous request if it is still pending
  140 + if (diffReq) {
  141 + diffReq.abort();
  142 + }
  143 +
  144 + diffReq = $.get("{% url "snippet_diff" %}", {
  145 + a: a,
  146 + b: b
  147 + }).done(function(data) {
  148 + $('#diff').html(data).slideDown('fast');
  149 + }).complete(function() {
  150 + diffReq = null;
  151 + });
  152 +
  153 + return false;
  154 + });
  155 +
  156 + var curLine = document.location.hash,
  157 + hashlist;
  158 +
  159 + if (curLine.substring(0, 2) === '#D') {
  160 + hashlist = curLine.substring(2).split(',');
  161 + if (hashlist.length === 2) {
  162 + console.log(hashlist);
  163 + $('#diffform input[name="a"][value="' + hashlist[0] + '"]').prop('checked', true);
  164 + $('#diffform input[name="b"][value="' + hashlist[1] + '"]').prop('checked', true);
  165 + $('#snippet-diff form').submit();
  166 + $('#snippet-diff').show();
  167 + }
  168 + }
  169 +
  170 + /* ------------------------------------------------------------------------
  171 +Line Highlighting
  172 +------------------------------------------------------------------------ */
  173 + if (curLine.substring(0, 2) === '#L') {
  174 + hashlist = curLine.substring(2).split(',');
  175 + if (hashlist.length > 0 && hashlist[0] !== '') {
  176 + $.each(hashlist, function(index, elem){
  177 + $('.code li#' + elem).addClass('marked');
  178 + });
  179 + }
  180 + }
  181 +
  182 + $('.code li').click(function(event) {
  183 + var hash = 'L';
  184 +
  185 + $(this).toggleClass("marked");
  186 +
  187 + $('.code li.marked').each(function (index, elem) {
  188 + if (hash !== 'L') hash += ',';
  189 + hash += $(elem).attr('id');
  190 + });
  191 +
  192 + window.location.hash = hash;
  193 +
  194 + e.preventDefault();
  195 + });
  196 +
  197 + /* ------------------------------------------------------------------------
  198 +Line Highlighting
  199 +------------------------------------------------------------------------ */
  200 + $('#toggleWordwrap').click(function(e){
  201 + e.preventDefault();
  202 + $('.code').toggleClass('wordwrap');
  203 + });
  204 +});
  205 +</script>
  206 +{% endblock %}
  207 +{% endblock %}
... ...
src/templates/dpaste/snippet_diff.html 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +{% load i18n %}
  2 +{% load url from future %}
  3 +
  4 +<h4>
  5 + {% blocktrans with fileA.get_absolute_url as filea_url and fileB.get_absolute_url as fileb_url and fileA.id as filea_id and fileB.id as fileb_id %}
  6 + Diff between <a href="{{ filea_url }}">#{{ filea_id }}</a> and <a href="{{ fileb_url }}">#{{ fileb_id }}</a>
  7 + {% endblocktrans %}
  8 +</h4>
  9 +
  10 +{% if snippet.lexer == 'diff' %}
  11 + {% include "dpaste/snippet_pre.html" %}
  12 +{% else %}
  13 + <p>{{ snippet.content }}</p>
  14 +{% endif %}
... ...
src/templates/dpaste/snippet_form.html 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +{% load i18n %}
  2 +
  3 +<form action="" method="post" class="form-horizontal">
  4 + {% csrf_token %}
  5 + {{ snippet_form.non_field_errors }}
  6 +
  7 + <div class="form-group superenter {% if is_new %}autofocus{% endif %} {% if snippet_form.content.errors %}has-error{% endif %}">
  8 + {{ snippet_form.content }}
  9 + </div>
  10 +
  11 + <div class="form-group">
  12 +
  13 + <div class="pull-left {% if snippet_form.lexer.errors %}has-error{% endif %}">
  14 + {{ snippet_form.lexer }}
  15 + </div>
  16 +
  17 + <div class="pull-right has-feedback">
  18 + <div class="input-group">
  19 + <span class="glyphicon glyphicon-trash input-group-addon"></span>
  20 + {{ snippet_form.expires }}
  21 + </div>
  22 +
  23 + </div>
  24 + </div>
  25 +
  26 + <div class="form-group">
  27 + <div class="well">
  28 + <input tabindex="0" type="submit" class="btn btn-primary" value="{% trans "Paste it" %}">
  29 + <span class="shortcut">Ctrl+⏎ ou ⌘+⏎</span>
  30 + </div>
  31 + </div>
  32 +
  33 +</form>
... ...
src/templates/dpaste/snippet_new.html 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +{% extends 'dpaste/base.html' %}
  2 +
  3 +{% load i18n %}
  4 +
  5 +{% block page %}
  6 + {% include "dpaste/snippet_form.html" %}
  7 +{% endblock %}
... ...