Commit 9398a6781686d7a8d5e27a2f364c59d903fbd606

Authored by Charles Oliveira
Committed by Matheus de Sousa Faria
1 parent 7daa556e

New Widget concept

Signed-off-by: Charles Oliveira <18oliveira.charles@gmail.com>
Signed-off-by: Gustavo Jaruga <darksshades@gmail.com>
colab/accounts/templates/accounts/user_update_form.html
1 1 {% extends "base.html" %}
2   -{% load i18n gravatar %}
  2 +{% load i18n gravatar plugins %}
3 3  
4 4 {% block head_js %}
5 5 <script>
... ... @@ -102,6 +102,14 @@ $(function() {
102 102 </script>
103 103 {% endblock %}
104 104  
  105 +{% block head %}
  106 + {{ block.super }}
  107 +
  108 + {% for widget in widgets %}
  109 + {{ widget.get_header }}
  110 + {% endfor %}
  111 +
  112 +{% endblock %}
105 113  
106 114 {% block main-content %}
107 115  
... ... @@ -113,88 +121,123 @@ $(function() {
113 121 <h3>{% gravatar user_.email 50 %} {{ user_.get_full_name }} ({{ user_.username }})</h3>
114 122 <a href="https://gravatar.com" target="_blank">
115 123 {% trans "Change your avatar at Gravatar.com" %}
116   - </a>
  124 + </a>{{ lala }}
117 125 </div>
118 126 <br>
119 127 <br>
120 128  
121   - <form method="post">
122   - {% csrf_token %}
123   -
124   - <div class="row">
125   - <div class="col-lg-8 col-md-7 col-sm-12 col-xm-12">
126   - {% for field in form %}
127   - <div class="col-lg-6 col-md-6 col-sm-12 col-xm-12">
128   - <div class="form-group{% if field.field.required %} required{% endif %}{% if field.errors %} alert alert-danger has-error{% endif %}">
129   - <label for="{{ field.name }}" class="control-label">
130   - {{ field.label }}
131   - </label>
132   - {{ field }}
133   - {{ field.errors }}
134   - </div>
135   - </div>
136   - {% endfor %}
137   - </div>
  129 + <!-- Start of navs -->
  130 + <ul class="nav nav-tabs">
  131 + <li class="active"><a data-toggle="pill" href="#profile">Profile</a></li>
  132 + {% for widget in widgets %}
  133 + <li>
  134 + <a data-toggle="pill" href="#{{ widget.identifier }}">{{ widget.name }}</a>
  135 + </li>
  136 + {% endfor %}
  137 + </ul>
  138 + <!-- End of navs -->
  139 + <style type="text/css">
  140 + .tab-pane{
  141 + border: 1px solid #DDD;
  142 + border-top: none;
  143 + padding: 10px;
  144 + }
138 145  
139   - <div class="col-lg-4 col-md-5 col-sm-12 col-xm-12">
140   - <div class="panel panel-default">
141   - <div class="panel-heading">
142   - <h3 class="panel-title">{% trans "Emails" %}</h3>
143   - </div>
144   - <div class="panel-body">
145   - <ul class="unstyled-list emails">
146   - {% for email in user_.emails.iterator %}
147   - <li>
148   - {% gravatar user_.email 30 %}
149   - <span class="email-address">{{ email.address }}</span>
150   - {% if email.address == user_.email %}
151   - <span class="label label-success">{% trans "Primary" %}</span>
152   - {% else %}
153   - <div class="text-right">
154   - <button class="btn btn-default set-primary" data-loading-text="{% trans 'Setting...' %}">{% trans "Set as Primary" %}</button>
155   - <button class="btn btn-danger delete-email" data-loading-text="{% trans 'Deleting...' %}">{% trans "Delete" %}</button>
156   - </div>
157   - {% endif %}
158   - <hr />
159   - </li>
  146 + .nav-tabs a:focus {
  147 + outline: none;
  148 + }
  149 + </style>
  150 + <div class="tab-content">
  151 + <div id="profile" class="tab-pane fade">
  152 + <form method="post">
  153 + {% csrf_token %}
  154 +
  155 + <div class="row">
  156 + <div class="col-lg-8 col-md-7 col-sm-12 col-xm-12">
  157 + {% for field in form %}
  158 + <div class="col-lg-6 col-md-6 col-sm-12 col-xm-12">
  159 + <div class="form-group{% if field.field.required %} required{% endif %}{% if field.errors %} alert alert-danger has-error{% endif %}">
  160 + <label for="{{ field.name }}" class="control-label">
  161 + {{ field.label }}
  162 + </label>
  163 + {{ field }}
  164 + {{ field.errors }}
  165 + </div>
  166 + </div>
160 167 {% endfor %}
161   - {% for email in user_.emails_not_validated.iterator %}
162   - <li>
163   - {% gravatar user_.email 30 %}
164   - <span class="email-address">{{ email.address }}</span>
165   - <div class="text-right">
166   - <button class="btn btn-default verify-email" data-loading-text="{% trans 'Sending verification...' %}"><span class="icon-warning-sign"></span> {% trans "Verify" %}</button>
167   - <button class="btn btn-danger delete-email">{% trans "Delete" %}</button>
  168 + </div>
  169 +
  170 + <div class="col-lg-4 col-md-5 col-sm-12 col-xm-12">
  171 + <div class="panel panel-default">
  172 + <div class="panel-heading">
  173 + <h3 class="panel-title">{% trans "Emails" %}</h3>
  174 + </div>
  175 + <div class="panel-body">
  176 + <ul class="unstyled-list emails">
  177 + {% for email in user_.emails.iterator %}
  178 + <li>
  179 + {% gravatar user_.email 30 %}
  180 + <span class="email-address">{{ email.address }}</span>
  181 + {% if email.address == user_.email %}
  182 + <span class="label label-success">{% trans "Primary" %}</span>
  183 + {% else %}
  184 + <div class="text-right">
  185 + <button class="btn btn-default set-primary" data-loading-text="{% trans 'Setting...' %}">{% trans "Set as Primary" %}</button>
  186 + <button class="btn btn-danger delete-email" data-loading-text="{% trans 'Deleting...' %}">{% trans "Delete" %}</button>
  187 + </div>
  188 + {% endif %}
  189 + <hr />
  190 + </li>
  191 + {% endfor %}
  192 + {% for email in user_.emails_not_validated.iterator %}
  193 + <li>
  194 + {% gravatar user_.email 30 %}
  195 + <span class="email-address">{{ email.address }}</span>
  196 + <div class="text-right">
  197 + <button class="btn btn-default verify-email" data-loading-text="{% trans 'Sending verification...' %}"><span class="icon-warning-sign"></span> {% trans "Verify" %}</button>
  198 + <button class="btn btn-danger delete-email">{% trans "Delete" %}</button>
  199 + </div>
  200 + <hr />
  201 + </li>
  202 + {% endfor %}
  203 + </ul>
  204 + <div class="form-group">
  205 + <label for="new_email">{% trans "Add another email address:" %}</label>
  206 + <input id="new_email" name="new_email" class="form-control" autocomplete="off" />
168 207 </div>
169   - <hr />
170   - </li>
171   - {% endfor %}
172   - </ul>
173   - <div class="form-group">
174   - <label for="new_email">{% trans "Add another email address:" %}</label>
175   - <input id="new_email" name="new_email" class="form-control" autocomplete="off" />
  208 + <button class="btn btn-primary pull-right" id="add-email">{% trans "Add" %}</button>
  209 + </div>
176 210 </div>
177   - <button class="btn btn-primary pull-right" id="add-email">{% trans "Add" %}</button>
178 211 </div>
179   - </div>
180   - </div>
181   - <div class="col-lg-4 col-md-5 col-sm-12 col-xm-12">
182   - <div class="panel panel-default">
183   - <div class="panel-heading">
184   - <h3 class="panel-title">
185   - {% trans 'Change Password' %}
186   - </h3>
  212 + <div class="col-lg-4 col-md-5 col-sm-12 col-xm-12">
  213 + <div class="panel panel-default">
  214 + <div class="panel-heading">
  215 + <h3 class="panel-title">
  216 + {% trans 'Change Password' %}
  217 + </h3>
  218 + </div>
  219 + <div class="panel-body">
  220 + <a href="{% url 'password_change' %}" class="btn btn-default btn-primary pull-right btn-block">{% trans "Change Password" %}</a>
  221 + </div>
  222 + </div>
187 223 </div>
188   - <div class="panel-body">
189   - <a href="{% url 'password_change' %}" class="btn btn-default btn-primary pull-right btn-block">{% trans "Change Password" %}</a>
  224 + </div>
  225 + <div class="row">
  226 + <div class="submit">
  227 + <button type="submit" class="btn btn-primary btn-lg btn-block">{% trans "Update" %}</button>
190 228 </div>
191 229 </div>
192   - </div>
  230 + </form>
  231 + </div>
  232 + <div id="code" class="tab-pane fade in active">
  233 + {% content_xpto %}
193 234 </div>
194   - <div class="row">
195   - <div class="submit">
196   - <button type="submit" class="btn btn-primary btn-lg btn-block">{% trans "Update" %}</button>
197   - </div>
  235 + <div id="social" class="tab-pane fade">
  236 + <p>Some content in menu 2.</p>
198 237 </div>
199   - </form>
  238 + </div>
  239 +
  240 +
  241 +
  242 +
200 243 {% endblock %}
... ...
colab/accounts/views.py
... ... @@ -15,6 +15,7 @@ from colab.super_archives.models import (EmailAddress,
15 15 EmailAddressValidation)
16 16 from colab.search.utils import get_collaboration_data, get_visible_threads
17 17 from colab.accounts.models import User
  18 +from colab.plugins.utils.widget_manager import WidgetManager
18 19  
19 20 from .forms import (UserCreationForm, ListsForm, UserUpdateForm)
20 21 from .utils import mailman
... ... @@ -42,6 +43,13 @@ class UserProfileUpdateView(UserProfileBaseMixin, UpdateView):
42 43  
43 44 return obj
44 45  
  46 + def get_context_data(self, **kwargs):
  47 + context = {}
  48 + context['widgets'] = WidgetManager.get_widgets('profile', self.request)
  49 + context['lala'] = 'lala123'
  50 + context.update(kwargs)
  51 + return super(UserProfileUpdateView, self).get_context_data(**context)
  52 +
45 53  
46 54 class UserProfileDetailView(UserProfileBaseMixin, DetailView):
47 55 template_name = 'accounts/user_detail.html'
... ...
colab/plugins/gitlab/__init__.py 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +
  2 +
  3 +default_app_config = 'colab.plugins.gitlab.apps.ProxyGitlabAppConfig'
  4 +
  5 +from colab.plugins.utils.widget_manager import WidgetManager
  6 +from colab.plugins.gitlab.widgets import GitlabProfileWidget
  7 +
  8 +WidgetManager.register_widget('profile', GitlabProfileWidget())
... ...
colab/plugins/gitlab/profile/diazo.xml 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +<rules
  2 + xmlns="http://namespaces.plone.org/diazo"
  3 + xmlns:css="http://namespaces.plone.org/diazo/css"
  4 + xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  5 +
  6 + <xsl:variable name="username" select="str:replace(//a/@href[(contains(., '/gitlab/u/'))], '/gitlab/u/', '')" />
  7 + <xsl:template match="a/@href[(contains(., '/profile/'))]">
  8 + <xsl:attribute name="href">/account/<xsl:value-of select="$username"/>/edit?code=<xsl:value-of select="."/>/</xsl:attribute>
  9 + </xsl:template>
  10 + <xsl:template match="form/@action[(contains(., '/gitlab/'))]">
  11 + <xsl:attribute name="action">/account/<xsl:value-of select="$username"/>/edit?code=<xsl:value-of select="."/>/</xsl:attribute>
  12 + </xsl:template>
  13 +
  14 + <!-- Drop colab stuff -->
  15 + <drop css:theme="nav.navbar-fixed-top" />
  16 + <drop css:theme="div.footer" />
  17 +
  18 + <!-- Drop unused tabs on gitlab -->
  19 + <drop content="div[@class='container']/ul/li[1]" />
  20 + <drop content="div[@class='container']/ul/li[3]" />
  21 + <drop content="div[@class='container']/ul/li[4]" />
  22 + <drop content="div[@class='container']/ul/li[7]" />
  23 + <drop content="fieldset[@class='update-username']" />
  24 +
  25 + <before theme-children="/html/head" content-children="/html/head" />
  26 + <before css:theme-children="#main-content" css:content-children="body" />
  27 +
  28 + <merge attributes="class" css:theme="body" css:content="body" />
  29 +
  30 + <!-- Add gitlab properties -->
  31 + <merge attributes="data-page" css:theme="body" css:content="body" />
  32 + <merge attributes="data-project-id" css:theme="body" css:content="body" />
  33 +
  34 + <drop css:content="#top-panel" />
  35 + <drop css:content=".navbar-gitlab" />
  36 +</rules>
... ...
colab/plugins/gitlab/templates/proxy/gitlab_profile.html 0 → 100644
... ... @@ -0,0 +1,50 @@
  1 +
  2 +{% load static from staticfiles %}
  3 +
  4 +{% block head_css %}
  5 +<style>
  6 + /* Reset left and with for .modal-dialog style (like gitlab does),
  7 + the bootstrap.css one makes it small */
  8 + @media screen and (min-width: 768px) {
  9 + .modal-dialog {
  10 + left: auto;
  11 + width: auto;
  12 + }
  13 + }
  14 +
  15 + div#main-content div.container {
  16 + width: 1110px;
  17 + }
  18 + div#main-content div.flash-container{
  19 + width: 85%;
  20 + }
  21 + #breadcrumbs {
  22 + border: 0 !important;
  23 + }
  24 +
  25 + #right-top-nav {
  26 + margin-right: 5em !important;
  27 + }
  28 +</style>
  29 +{% endblock %}
  30 +
  31 +{% block head_js %}
  32 +<script>jQuery.noConflict();</script>
  33 +{% endblock %}
  34 +<body>
  35 +</body>
  36 +<div id="main-content"></div>
  37 +<script type="text/javascript">
  38 + jQuery(function(){
  39 + // bootstrap.css forces .hide {display:none!important}, and this makes
  40 + // gitlab .hide elements NEVER have a display:block, so
  41 + // instead of editing bootstrap.css, we just removed '.hide' css class and
  42 + // toggled
  43 + jQuery('.hide').removeClass('hide').css('display', 'none');
  44 + });
  45 +
  46 + // Extremelly ugly solutions to add Colab's CSRF token to Gitlab forms
  47 + // add CSRF token to HTTP header***
  48 + jQuery('div#code form').append(jQuery("input[name='csrfmiddlewaretoken']"));
  49 + $('a.delete-key').attr('data-method', 'delete\" type=\"hidden\" /> <input name=\"csrfmiddlewaretoken\" value=\"' + jQuery("input[name='csrfmiddlewaretoken']").val());
  50 +</script>
... ...
colab/plugins/gitlab/urls.py 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +
  2 +from django.conf.urls import patterns, url
  3 +
  4 +from .views import GitlabProxyView, GitlabProfileProxyView
  5 +
  6 +urlpatterns = patterns('',
  7 + # Gitlab URLs
  8 + #url(r'(?P<path>profile.*)$', GitlabProfileProxyView.as_view(), name='gitlab'),
  9 + url(r'^(?P<path>.*)$', GitlabProxyView.as_view(), name='gitlab'),
  10 +)
... ...
colab/plugins/gitlab/views.py 0 → 100644
... ... @@ -0,0 +1,22 @@
  1 +
  2 +from ..utils.views import ColabProxyView
  3 +import os, sys
  4 +
  5 +
  6 +class GitlabProxyView(ColabProxyView):
  7 + app_label = 'gitlab'
  8 + diazo_theme_template = 'proxy/gitlab.html'
  9 +
  10 +
  11 +class GitlabProfileProxyView(ColabProxyView):
  12 + app_label = 'gitlab'
  13 + diazo_theme_template = 'proxy/gitlab_profile.html'
  14 +
  15 + @property
  16 + def diazo_rules(self):
  17 + child_class_file = sys.modules[self.__module__].__file__
  18 + app_path = os.path.abspath(os.path.dirname(child_class_file))
  19 + diazo_path = os.path.join(app_path, 'profile/diazo.xml')
  20 +
  21 + self.log.debug("diazo_rules: %s", diazo_path)
  22 + return diazo_path
... ...
colab/plugins/gitlab/widgets.py 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +from colab.plugins.gitlab.views import GitlabProxyView, GitlabProfileProxyView
  2 +from colab.plugins.utils.widget_manager import Widget
  3 +from django.utils.safestring import mark_safe
  4 +
  5 +
  6 +class GitlabProfileWidget(GitlabProxyView, Widget):
  7 + identifier = 'code'
  8 + name = 'Gitlab Profile'
  9 + default_url = '/gitlab/profile/account'
  10 +
  11 + def generate_content(self, request):
  12 + requested_url = request.GET.get('code', self.default_url)
  13 + g = GitlabProfileProxyView()
  14 + r = g.dispatch(request, requested_url)
  15 + if r.status_code == 302:
  16 + location = r.get('Location')
  17 + requested_url = location[location.find('/{}/'.format(self.app_label)):]
  18 + request.method = 'GET'
  19 + r = g.dispatch(request, requested_url)
  20 +
  21 + return "<div>" + r.content + "</div>"
0 22 \ No newline at end of file
... ...
colab/plugins/templatetags/plugins.py
... ... @@ -51,3 +51,23 @@ def plugins_menu(context):
51 51  
52 52 cache.set(cache_key, menu)
53 53 return menu
  54 +
  55 +import requests
  56 +from django.conf import settings
  57 +from colab.plugins.gitlab.views import GitlabProfileProxyView
  58 +@register.simple_tag(takes_context=True)
  59 +def content_xpto(context):
  60 + request = context['request']
  61 + requested_url = request.GET.get('code', '/gitlab/profile/account')
  62 + print "requested_url1 = " + requested_url
  63 +
  64 + g = GitlabProfileProxyView()
  65 + r = g.dispatch(request, requested_url)
  66 + if r.status_code == 302:
  67 + location = r.get('Location')
  68 + requested_url = location[location.find('/gitlab/'):]
  69 + request.method = 'GET'
  70 + print "requested_url2 = " + requested_url
  71 + r = g.dispatch(request, requested_url)
  72 +
  73 + return "<div>" + r.content + "</div>"
... ...
colab/plugins/utils/widget_manager.py 0 → 100644
... ... @@ -0,0 +1,44 @@
  1 +
  2 +class Widget:
  3 + identifier = None
  4 + name = None
  5 + default_url = None
  6 + content = None
  7 +
  8 + def get_body(self):
  9 + # avoiding regex in favor of performance
  10 + start = content.find('<body>')
  11 + end = content.find('</body>')
  12 + head = content[start + len('<body>'):end]
  13 + return head
  14 +
  15 + def get_header(self):
  16 + # avoiding regex in favor of performance
  17 + start = content.find('<head>')
  18 + end = content.find('</head>')
  19 + head = content[start + len('<head>'):end]
  20 + return head
  21 +
  22 + def generate_content(self, request=None):
  23 + self.content = ''
  24 +
  25 +
  26 +class WidgetManager(object):
  27 + widget_categories = {}
  28 +
  29 + @staticmethod
  30 + def register_widget(category, widget):
  31 + if not WidgetManager.widget_categories.has_key(category):
  32 + WidgetManager.widget_categories[category] = []
  33 +
  34 + WidgetManager.widget_categories[category].append(widget)
  35 +
  36 + @staticmethod
  37 + def get_widgets(category, request=None):
  38 + if not WidgetManager.widget_categories.has_key(category):
  39 + return []
  40 +
  41 + widgets = WidgetManager.widget_categories[category]
  42 + for widget in widgets:
  43 + widget.generate_content(request)
  44 + return widgets
... ...
colab/urls.py
... ... @@ -3,7 +3,7 @@ from django.conf import settings
3 3 from django.views.generic import TemplateView
4 4 from django.contrib import admin
5 5 from django.views.generic import RedirectView
6   -
  6 +from accounts.views import UserProfileUpdateView
7 7  
8 8 admin.autodiscover()
9 9  
... ...
diagrama_classes.asta 0 → 100644
No preview for this file type