Implement featured projects

This commit is contained in:
Drew DeVault 2020-04-28 14:08:56 -04:00
parent 19c9a87682
commit 102fca490c
7 changed files with 91 additions and 8 deletions

View File

@ -1,7 +1,8 @@
from flask import Blueprint, render_template, request, redirect, url_for
from hubsrht.decorators import adminrequired
from hubsrht.projects import ProjectAccess, get_project
from hubsrht.services import git, hg
from hubsrht.types import Event, EventType
from hubsrht.types import Feature, Event, EventType
from hubsrht.types import Project, RepoType, Visibility
from srht.database import db
from srht.flask import paginate_query
@ -136,3 +137,18 @@ def delete_POST(owner, project_name):
db.session.delete(project)
db.session.commit()
return redirect(url_for("public.index"))
@projects.route("/<owner>/<project_name>/feature", methods=["POST"])
@adminrequired
def feature_POST(owner, project_name):
owner, project = get_project(owner, project_name, ProjectAccess.read)
valid = Validation(request)
feature = Feature()
feature.project_id = project.id
feature.summary = valid.require("summary")
if not valid.ok:
abort(400) # admin-only route, who cares
db.session.add(feature)
db.session.commit()
return redirect(url_for("public.project_index"))

View File

@ -1,5 +1,5 @@
from flask import Blueprint, render_template, request
from hubsrht.types import Project, Event, EventType, Visibility
from hubsrht.types import Project, Feature, Event, EventType, Visibility, User
from srht.flask import paginate_query
from srht.oauth import current_user, loginrequired
from srht.search import search_by
@ -48,5 +48,12 @@ def project_index():
projects, pagination = paginate_query(projects)
features = (Feature.query
.join(Project, Feature.project_id == Project.id)
.join(User, Project.owner_id == User.id)
.filter(Project.visibility == Visibility.public)
.order_by(Feature.created.desc())
.limit(5)).all()
return render_template("project-index.html", projects=projects,
search=search, sort=sort, **pagination)
search=search, features=features, sort=sort, **pagination)

14
hubsrht/decorators.py Normal file
View File

@ -0,0 +1,14 @@
from flask import redirect, abort, current_app, request
from functools import wraps
from srht.oauth import current_user, UserType
def adminrequired(f):
@wraps(f)
def wrapper(*args, **kwargs):
if not current_user:
return redirect(current_app.oauth_service.oauth_url(request.url))
elif current_user.user_type != UserType.admin:
abort(403)
else:
return f(*args, **kwargs)
return wrapper

View File

@ -76,12 +76,16 @@
<div class="col-lg-4">
<h3>Featured projects</h3>
<div class="event-list">
{% for i in range(3) %}
<a href="#">~sircmpwn</a>/<a href="#">sourcehut</a>
{% for feature in features %}
<a href="{{url_for("users.summary_GET",
username=feature.project.owner.username)}}"
>{{feature.project.owner.canonical_name}}</a>/<a
href="{{url_for("projects.summary_GET",
owner=feature.project.owner.canonical_name,
project_name=feature.project.name)}}"
>{{feature.project.name}}</a>
<blockquote style="margin-top: 0.5rem">
SourceHut itself is a free and open-source software project. You
can read and contribute to the code, and install it on your own
servers.
{{feature.summary | md}}
</blockquote>
{% endfor %}
</div>

View File

@ -203,5 +203,30 @@
</div>
{% endif %}
</div>
{% if current_user and current_user.user_type.value == "admin" %}
<div class="row" style="margin-top: 5rem">
<div class="col-md-6">
<h3>Feature this project</h3>
<form action="{{url_for("projects.feature_POST",
owner=project.owner.canonical_name,
project_name=project.name)}}"
method="POST">
{{csrf_token()}}
<div class="form-group">
<textarea
class="form-control"
name="summary"
rows="3"
placeholder="Featured project summary"
></textarea>
</div>
<button
type="submit"
class="btn btn-primary"
>Feature project {{icon('caret-right')}}</button>
</form>
</div>
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -11,6 +11,7 @@ class Visibility(Enum):
private = "private"
from hubsrht.types.event import Event, EventType
from hubsrht.types.feature import Feature
from hubsrht.types.mailinglist import MailingList
from hubsrht.types.project import Project
from hubsrht.types.sourcerepo import SourceRepo, RepoType

16
hubsrht/types/feature.py Normal file
View File

@ -0,0 +1,16 @@
import sqlalchemy as sa
import sqlalchemy_utils as sau
from hubsrht.types import Visibility
from srht.database import Base
class Feature(Base):
__tablename__ = "features"
id = sa.Column(sa.Integer, primary_key=True)
created = sa.Column(sa.DateTime, nullable=False)
project_id = sa.Column(sa.Integer,
sa.ForeignKey("project.id", ondelete="CASCADE"),
nullable=False)
project = sa.orm.relationship("Project")
summary = sa.Column(sa.Unicode(), nullable=False)