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:
parent
a3a37ee689
commit
2951309f9c
9 changed files with 204 additions and 3 deletions
|
@ -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)
|
||||
|
|
29
events/migrations/0036_auto_20180701_2148.py
Normal file
29
events/migrations/0036_auto_20180701_2148.py
Normal 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),
|
||||
),
|
||||
]
|
|
@ -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
|
||||
|
|
91
get_together/templates/get_together/teams/about_team.html
Normal file
91
get_together/templates/get_together/teams/about_team.html
Normal 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 %}
|
||||
|
|
@ -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/>
|
||||
|
||||
|
|
|
@ -3,3 +3,4 @@ from django.test import TestCase
|
|||
from .events import *
|
||||
from .event_reminder import *
|
||||
from .speakers import *
|
||||
from .teams import *
|
||||
|
|
54
get_together/tests/teams.py
Normal file
54
get_together/tests/teams.py
Normal 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)
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue