From cb1ad43ccf8f8ed8e17fc35b9871ddf35f8bcc54 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stefan=20K=C3=B6gl?= Date: Tue, 20 Nov 2012 15:22:20 +0100 Subject: [PATCH] add twitter, about text to user profile --- mygpo/publisher/views.py | 4 +- mygpo/share/templates/userpage.html | 29 +++++- mygpo/share/userpage.py | 3 + mygpo/users/models.py | 2 + mygpo/web/forms.py | 6 ++ mygpo/web/templates/account.html | 192 +++++++++++++++++++++++------------- mygpo/web/templates/base.html | 2 +- mygpo/web/urls.py | 6 +- mygpo/web/utils.py | 8 ++ mygpo/web/views/settings.py | 34 ++++++- 10 files changed, 214 insertions(+), 72 deletions(-) rewrite mygpo/web/templates/account.html (72%) diff --git a/mygpo/publisher/views.py b/mygpo/publisher/views.py index 897f88bc..747b0f52 100644 --- a/mygpo/publisher/views.py +++ b/mygpo/publisher/views.py @@ -20,7 +20,7 @@ from mygpo.web.views.episode import oldid_decorator, slug_id_decorator from mygpo.web.views.podcast import \ slug_id_decorator as podcast_slug_id_decorator, \ oldid_decorator as podcast_oldid_decorator -from mygpo.web.utils import get_podcast_link_target +from mygpo.web.utils import get_podcast_link_target, normalize_twitter from django.contrib.sites.models import RequestSite from mygpo.data.feeddownloader import PodcastUpdater from mygpo.decorators import requires_token, allowed_methods @@ -150,7 +150,7 @@ def update_podcast(request, podcast): @cache_control(private=True) @require_publisher def save_podcast(request, podcast): - twitter = request.POST.get('twitter', '').replace('@', '').strip() + twitter = normalize_twitter(request.POST.get('twitter', '')) update_additional_data(podcast, twitter) messages.success(request, _('Data updated')) url = get_podcast_link_target(podcast, 'podcast-publisher-detail') diff --git a/mygpo/share/templates/userpage.html b/mygpo/share/templates/userpage.html index c763d10d..7165d133 100644 --- a/mygpo/share/templates/userpage.html +++ b/mygpo/share/templates/userpage.html @@ -21,7 +21,22 @@

{{ page_user.username }}

- + + {% blocktrans %}a user on {{ site }}{% endblocktrans %} + {% if user.twitter %} + ยท + {% endif %} + + + +
+ {% if user.about %} + {{ user.about|markdown }} + {% else %} + {% blocktrans with user.username as username %}{{ username }} is sharing his favorite podcasts on {{ site }}.{% endblocktrans %} + {% endif %} + +
{% endblock %} {% block content %} @@ -146,6 +161,18 @@ {% block sidebar %} + {% if user == page_user %} + +
+

{% trans "That's You!" %}

+ + {% trans "Edit your profile" %} + +
+ + {% endif %} + +

{% trans "Stats" %}

    diff --git a/mygpo/share/userpage.py b/mygpo/share/userpage.py index 9d166130..f2c46f93 100644 --- a/mygpo/share/userpage.py +++ b/mygpo/share/userpage.py @@ -5,6 +5,7 @@ import gevent from django.shortcuts import render from django.views.generic.base import View from django.utils.decorators import method_decorator +from django.contrib.sites.models import RequestSite from mygpo.users.models import User from mygpo.users.models import HistoryEntry @@ -28,6 +29,7 @@ class UserpageView(GeventView): user = User.get_user(username) month_ago = datetime.today() - timedelta(days=31) + site = RequestSite(request) context_funs = { 'lists': gevent.spawn(self.get_podcast_lists, user), @@ -42,6 +44,7 @@ class UserpageView(GeventView): context = { 'page_user': user, + 'site': site.domain, 'subscriptions_token': user.get_token('subscriptions_token'), 'favorite_feeds_token': user.get_token('favorite_feeds_token'), } diff --git a/mygpo/users/models.py b/mygpo/users/models.py index 5cd68250..f7ce3c9c 100644 --- a/mygpo/users/models.py +++ b/mygpo/users/models.py @@ -471,6 +471,8 @@ class User(BaseUser, SyncedDevicesMixin): published_objects = StringListProperty() deleted = BooleanProperty(default=False) suggestions_up_to_date = BooleanProperty(default=False) + twitter = StringProperty() + about = StringProperty() # token for accessing subscriptions of this use subscriptions_token = StringProperty(default=None) diff --git a/mygpo/web/forms.py b/mygpo/web/forms.py index b3425ab5..6c0d9e14 100644 --- a/mygpo/web/forms.py +++ b/mygpo/web/forms.py @@ -35,6 +35,12 @@ class UserAccountForm(forms.Form): return True + +class ProfileForm(forms.Form): + twitter = forms.CharField(label=_(u'Twitter'), required=False) + about = forms.CharField(label=_(u'A few words about you'), required=False, widget=forms.Textarea, help_text='You can use Markdown') + + class DeviceForm(forms.Form): """ form for editing device information by a user. diff --git a/mygpo/web/templates/account.html b/mygpo/web/templates/account.html dissimilarity index 72% index 906ee2ba..4245ea8f 100644 --- a/mygpo/web/templates/account.html +++ b/mygpo/web/templates/account.html @@ -1,66 +1,126 @@ -{% extends "base.html" %} -{% load url from future %} -{% load i18n %} - -{% load menu %} -{% block mainmenu %}{{ "/account/"|main_menu }}{% endblock %} -{% block sectionmenu %}{{ "/account/"|section_menu }}{% endblock %} - -{% block title %}{% trans "Account Settings" %}{% endblock %} - -{% block header %} -

    {% trans "Account Settings" %}

    -{% endblock %} - -{% block content %} -
    - {% csrf_token %} -

    {% trans "Account Data" %}

    - -
    - -
    - -
    - {{ form.email }} -
    -
    - -
    - -
    - {{ form.password_current }} -
    -
    - -
    - -
    - {{ form.password1 }} -
    -
    - -
    - -
    - {{ form.password2 }} -
    -
    - -
    -
    - -
    -
    - -
    -
    - -

    {% trans "Delete Account" %}

    - - - -{% endblock %} - +{% extends "base.html" %} +{% load url from future %} +{% load i18n %} + +{% load menu %} +{% block mainmenu %}{{ "/account/"|main_menu }}{% endblock %} +{% block sectionmenu %}{{ "/account/"|section_menu }}{% endblock %} + +{% block title %}{% trans "Account Settings" %}{% endblock %} + +{% block header %} +

    {% trans "Account Settings" %}

    +{% endblock %} + +{% block content %} + +
    + + + +
    + +
    + {% csrf_token %} + +
    + {% trans "Account Data" %} + +
    + +
    + {{ form.email }} +
    +
    + +
    + +
    + {{ form.password_current }} +
    +
    + +
    + +
    + {{ form.password1 }} +
    +
    + +
    + +
    + {{ form.password2 }} +
    +
    + +
    +
    + +
    +
    + +
    +
    + +

    {% trans "Delete Account" %}

    + + + +
    + +
    + +
    + {% csrf_token %} + {% trans "Public profile" %} + + + {% trans "for your userpage" %} + + + + +
    + +
    + +
    +
    + @ + +
    +
    +
    + +
    + +
    + {{ profile_form.about }} +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +{% endblock %} diff --git a/mygpo/web/templates/base.html b/mygpo/web/templates/base.html index 9a259dc7..c0dc9fad 100644 --- a/mygpo/web/templates/base.html +++ b/mygpo/web/templates/base.html @@ -68,7 +68,7 @@ diff --git a/mygpo/web/urls.py b/mygpo/web/urls.py index 4a8444e7..d7ae5954 100644 --- a/mygpo/web/urls.py +++ b/mygpo/web/urls.py @@ -81,12 +81,16 @@ urlpatterns += patterns('mygpo.web.views.episode', ) from mygpo.web.views.settings import DefaultPrivacySettings, \ - PodcastPrivacySettings + PodcastPrivacySettings, ProfileView urlpatterns += patterns('mygpo.web.views.settings', url(r'^account/$', 'account', name='account'), url(r'^account/privacy$', 'privacy', name='privacy'), + url(r'^account/profile$', + ProfileView.as_view(), + name='profile'), + url(r'^account/privacy/default-public$', DefaultPrivacySettings.as_view(public=True), name='privacy_default_public'), diff --git a/mygpo/web/utils.py b/mygpo/web/utils.py index ea8d4279..6b77c6ee 100644 --- a/mygpo/web/utils.py +++ b/mygpo/web/utils.py @@ -229,3 +229,11 @@ def fetch_episode_data(episodes, podcasts={}): return episode return map(set_podcast, episodes) + + +# doesn't include the '@' because it's not stored as part of a twitter handle +TWITTER_CHARS = string.ascii_letters + string.digits + '_' + +def normalize_twitter(s): + """ normalize user input that is supposed to be a Twitter handle """ + return "".join(i for i in s if i in TWITTER_CHARS) diff --git a/mygpo/web/views/settings.py b/mygpo/web/views/settings.py index ea54473f..616d517b 100644 --- a/mygpo/web/views/settings.py +++ b/mygpo/web/views/settings.py @@ -28,12 +28,14 @@ from django.views.decorators.vary import vary_on_cookie from django.views.decorators.cache import never_cache, cache_control from django.utils.decorators import method_decorator from django.views.generic.base import View +from django.utils.html import strip_tags from django_couchdb_utils.auth.models import UsernameException, \ PasswordException from mygpo.decorators import allowed_methods, repeat_on_conflict -from mygpo.web.forms import UserAccountForm +from mygpo.web.forms import UserAccountForm, ProfileForm +from mygpo.web.utils import normalize_twitter from mygpo.db.couchdb.podcast import podcast_by_id, podcasts_to_dict from mygpo.db.couchdb.podcast_state import podcast_state_for_user_podcast, \ subscriptions_by_user @@ -47,6 +49,13 @@ def account(request): if request.method == 'GET': + userpage_token = request.user.get_token('userpage_token') + + profile_form = ProfileForm({ + 'twitter': request.user.twitter, + 'about': request.user.about, + }) + form = UserAccountForm({ 'email': request.user.email, 'public': request.user.settings.get('public_subscriptions', True) @@ -54,6 +63,8 @@ def account(request): return render(request, 'account.html', { 'form': form, + 'profile_form': profile_form, + 'userpage_token': userpage_token, }) try: @@ -85,6 +96,27 @@ def account(request): }) +class ProfileView(View): + """ Updates the public profile and redirects back to the account view """ + + def post(self, request): + user = request.user + + form = ProfileForm(request.POST) + + if not form.is_valid(): + raise ValueError(_('Oops! Something went wrong. Please double-check the data you entered.')) + + request.user.twitter = normalize_twitter(form.cleaned_data['twitter']) + request.user.about = strip_tags(form.cleaned_data['about']) + + request.user.save() + messages.success(request, _('Data updated')) + + return HttpResponseRedirect(reverse('account')) + + + @login_required @never_cache @allowed_methods(['GET', 'POST']) -- 2.11.4.GIT