Issue 65: Team About Page

Addresses #65

* Added a team about page.
* The page is rendered at /<team_slug>/about/.
* If the about_page field is None, then the user is redirected to the team
  page.
* A link was added from the team page to view the about page
* A link on the about page was added to return to the team page
* Tests of redirect functionality were added
This commit is contained in:
Briar Rose Schreiber 2018-07-01 15:45:54 -07:00
parent a3a37ee689
commit 2951309f9c
9 changed files with 204 additions and 3 deletions

View file

@ -158,6 +158,7 @@ class TeamForm(forms.ModelForm):
fields = [
'name',
'description',
'about_page',
'category',
'city',
'web_url',
@ -192,7 +193,7 @@ class NewTeamForm(forms.ModelForm):
class TeamDefinitionForm(forms.ModelForm):
class Meta:
model = Team
fields = ['category', 'web_url', 'description']
fields = ['category', 'web_url', 'description', 'about_page']
class DeleteTeamForm(forms.Form):
confirm = forms.BooleanField(label="Yes, delete team", required=True)

View file

@ -0,0 +1,29 @@
# Generated by Django 2.0 on 2018-07-01 21:48
from django.db import migrations, models
import imagekit.models.fields
class Migration(migrations.Migration):
dependencies = [
('events', '0035_add_event_status'),
]
operations = [
migrations.AddField(
model_name='team',
name='about_page',
field=models.TextField(blank=True, null=True),
),
migrations.AlterField(
model_name='sponsor',
name='logo',
field=imagekit.models.fields.ProcessedImageField(blank=True, help_text='Will be scaled and cropped to max 250x200 px.', upload_to='sponsors', verbose_name='Logo'),
),
migrations.AlterField(
model_name='team',
name='slug',
field=models.CharField(max_length=256, unique=True),
),
]

View file

@ -244,6 +244,8 @@ class Team(models.Model):
description = models.TextField(blank=True, null=True)
about_page = models.TextField(blank=True, null=True)
country = models.ForeignKey(Country, on_delete=models.CASCADE)
spr = models.ForeignKey(SPR, null=True, blank=True, on_delete=models.CASCADE)
city = models.ForeignKey(City, null=True, blank=True, on_delete=models.CASCADE)
@ -319,6 +321,9 @@ class Team(models.Model):
self.slug = '%s-%s' % (new_slug, self.id)
super().save(*args, **kwargs) # Call the "real" save() method.
def get_absolute_url(self):
return reverse('show-team-by-slug', kwargs={'team_slug': self.slug})
class Member(models.Model):
NORMAL=0

View file

@ -0,0 +1,91 @@
{% extends "get_together/base.html" %}
{% load static markup tz %}
{% block add_to_title %} | {{team.name}}{% endblock %}
{% block styles %}
<style>
.gt-profile {
position: relative;
}
.gt-profile .gt-profile-badges {
position: absolute;
top: 16px;
left: 6px;
}
</style>
{% endblock %}
{% block content %}
<div class="fluid-container">
<div class="row">
<div class="col-sm-9">
{% if team.banner_img %}
<div class="team-banner">
<img class="card-img-top" src="{{ team.banner_img.url }}" alt="{{team.name}}'s cover image" height="200px" width="825px">
<h2 class="team-title">Welcome to {{ team.name }}</h2>
</div>
{% else %}
<h2>About {{ team.name }}</h2>
{% endif %}
{% if can_edit_team %}
<a href="{% url 'edit-team' team.id %}" class="btn btn-secondary btn-sm"><i class="fa fa-pencil"></i> Edit Team</a>
<a href="{% url 'manage-members' team.id %}" class="btn btn-secondary btn-sm"><i class="fa fa-users"></i> Manage Members</a>
{% endif %}
{% if is_member %}
{% if not team.owner_profile == request.user.profile %}<a href="{% url 'leave-team' team.id %}" class="btn btn-danger btn-sm">Leave Team</a>{% endif %}
{% else %}
<a href="{% url 'join-team' team.id %}" class="btn btn-success btn-sm">Join Team</a>
{% endif %}
<hr/>
<table >
{% if team.description %}
<tr>
<td colspan="2"><p>{{ team.description|markdown }}</p></td>
</tr>
{% endif %}
{% if team.organization %}
<tr>
<td width="120px"><b>Organization:</b></td><td><a href="{% url 'show-org' team.organization.slug %}">{{ team.organization.name }}</a></td>
</tr>
{% endif %}
{% if team.web_url %}
<tr>
<td width="120px"><b>Website:</b></td><td><a href="{{ team.web_url }}" target="_blank">{{ team.web_url }}</a></td>
</tr>
{% endif %}
<tr>
<td width="120px"><b>Events:</b></td><td><a href="{% url 'show-team-by-slug' team.slug %}">Return to Events</a></td>
</tr>
</table>
<hr/>
<div class="container">
{{ team.about_page|markdown }}
</div>
<br/>
</div>
<div class="col-sm-3">
<div class="container">
<h4>Members</h4><hr/>
{% for member in member_list %}
<div class="row mb-3">
<div class="col media gt-profile">
<img class="mr-1 gt-profile-avatar" src="{{member.user.avatar_url}}" width="32px" height="32px">
<span class="gt-profile-badges">{% for badge in member.user.user.account.badges.all %}<img class="mr-0 gt-profile-badge" src="{{badge.img_url}}" title="{{badge.name}}" width="16px" height="16px">{% endfor %}</span>
<div class="media-body">
<h6 class="mt-0 mb-0"><a href="{% url 'show-profile' member.user.id %}" title="{{member.user}}'s profile">{{member.user}}</a></h6>
{% if member.role > 0 %}<small class="text-muted">{{ member.role_name }}</small>{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -57,6 +57,11 @@
<td width="120px"><b>Website:</b></td><td><a href="{{ team.web_url }}" target="_blank">{{ team.web_url }}</a></td>
</tr>
{% endif %}
{% if team.about_page %}
<tr>
<td width="120px"><b>About:</b></td><td><a href="{% url 'show-team-about-by-slug' team.slug %}">Learn More about {{ team.name }}</a></td>
</tr>
{% endif %}
</table>
<hr/>

View file

@ -3,3 +3,4 @@ from django.test import TestCase
from .events import *
from .event_reminder import *
from .speakers import *
from .teams import *

View file

@ -0,0 +1,54 @@
from django.test import TestCase, Client
from django.shortcuts import resolve_url
from django.utils import timezone
from django.urls import reverse
from model_mommy import mommy
import mock
import datetime
from django.contrib.auth.models import User
from events.ipstack import get_ipstack_geocoder
from events.models import Team
# Create your tests here.
class TeamDisplayTests(TestCase):
def setUp(self):
super().setUp()
def tearDown(self):
super().tearDown()
def test_show_team(self):
team = mommy.make(Team)
team.save()
team_url = team.get_absolute_url()
c = Client()
response = c.get(team_url)
assert(response.status_code == 200)
def test_show_about_team(self):
team = mommy.make(Team)
team.about_page = "about this team!"
team.save()
team_about_url = reverse('show-team-about-by-slug', kwargs={'team_slug': team.slug})
c = Client()
response = c.get(team_about_url)
assert(response.status_code == 200)
def test_show_about_team_redirects_if_none(self):
team = mommy.make(Team)
team.about_page = ""
team.save()
team_about_url = reverse('show-team-about-by-slug', kwargs={'team_slug': team.slug})
c = Client()
response = c.get(team_about_url)
assert(response.status_code == 302)

View file

@ -115,6 +115,7 @@ urlpatterns = [
path('activity_pub/', include('events.activity_pub.urls')),
path('<str:team_slug>/', views.show_team_by_slug, name='show-team-by-slug'),
path('<str:team_slug>/about/', views.show_team_about_by_slug, name='show-team-about-by-slug'),
]
if settings.DEBUG:
urlpatterns = urlpatterns + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View file

@ -49,12 +49,10 @@ def show_team_by_slug(request, team_slug):
team = get_object_or_404(Team, slug=team_slug)
return show_team(request, team)
def show_team_by_id(request, team_id):
team = get_object_or_404(Team, id=team_id)
return redirect('show-team-by-slug', team_slug=team.slug)
def show_team(request, team):
upcoming_events = Event.objects.filter(team=team, end_time__gt=datetime.datetime.now()).order_by('start_time')
recent_events = Event.objects.filter(team=team, end_time__lte=datetime.datetime.now()).order_by('-start_time')[:5]
@ -69,6 +67,22 @@ def show_team(request, team):
}
return render(request, 'get_together/teams/show_team.html', context)
def show_team_about_by_slug(request, team_slug):
team = get_object_or_404(Team, slug=team_slug)
if team.about_page:
return show_team_about(request, team)
else:
return redirect('show-team-by-slug', team_slug=team.slug)
def show_team_about(request, team):
context = {
'team': team,
'is_member': request.user.profile in team.members.all(),
'member_list': Member.objects.filter(team=team).order_by('-role', 'joined_date'),
'can_create_event': request.user.profile.can_create_event(team),
'can_edit_team': request.user.profile.can_edit_team(team),
}
return render(request, 'get_together/teams/about_team.html', context)
@login_required
def create_team(request, *args, **kwargs):