Refactor package URL generation

This commit is contained in:
rubenwardy 2021-07-24 04:30:14 +01:00
parent 187202d363
commit 4e83adc032
35 changed files with 129 additions and 198 deletions

@ -29,22 +29,22 @@ def get_package_tabs(user: User, package: Package):
{
"id": "edit",
"title": "Edit Details",
"url": package.getEditURL()
"url": package.getURL("packages.create_edit")
},
{
"id": "releases",
"title": "Releases",
"url": package.getReleaseListURL()
"url": package.getURL("packages.list_releases")
},
{
"id": "screenshots",
"title": "Screenshots",
"url": package.getEditScreenshotsURL()
"url": package.getURL("packages.screenshots")
},
{
"id": "maintainers",
"title": "Maintainers",
"url": package.getEditMaintainersURL()
"url": package.getURL("packages.edit_maintainers")
},
{
"id": "audit",
@ -59,7 +59,7 @@ def get_package_tabs(user: User, package: Package):
{
"id": "remove",
"title": "Remove",
"url": package.getRemoveURL()
"url": package.getURL("packages.remove")
}
]

@ -70,7 +70,7 @@ def list_all():
if qb.lucky:
package = query.first()
if package:
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
topic = qb.buildTopicQuery().first()
if qb.search and topic:
@ -206,7 +206,7 @@ def download(package):
return "", 204
else:
flash("No download available.", "danger")
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
else:
return redirect(release.getDownloadURL())
@ -263,7 +263,7 @@ def create_edit(author=None, name=None):
if package is None:
abort(404)
if not package.checkPerm(current_user, Permission.EDIT_PACKAGE):
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
author = package.author
@ -321,11 +321,11 @@ def create_edit(author=None, name=None):
if wasNew and package.repo is not None:
importRepoScreenshot.delay(package.id)
next_url = package.getDetailsURL()
next_url = package.getURL("packages.view")
if wasNew and ("WTFPL" in package.license.name or "WTFPL" in package.media_license.name):
next_url = url_for("flatpage", path="help/wtfpl", r=next_url)
elif wasNew:
next_url = package.getSetupReleasesURL()
next_url = package.getURL("packages.setup_releases")
return redirect(next_url)
except LogicError as e:
@ -353,7 +353,7 @@ def move_to_state(package):
if not package.canMoveToState(current_user, state):
flash("You don't have permission to do that", "danger")
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
package.state = state
msg = "Marked {} as {}".format(package.title, state.value)
@ -368,9 +368,9 @@ def move_to_state(package):
msg = "Approved {}".format(package.title)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_APPROVAL, msg, package.getDetailsURL(), package)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_APPROVAL, msg, package.getURL("packages.view"), package)
severity = AuditSeverity.NORMAL if current_user in package.maintainers else AuditSeverity.EDITOR
addAuditLog(severity, current_user, msg, package.getDetailsURL(), package)
addAuditLog(severity, current_user, msg, package.getURL("packages.view"), package)
db.session.commit()
@ -381,7 +381,7 @@ def move_to_state(package):
else:
return redirect(url_for('threads.new', pid=package.id, title='Package approval comments'))
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
@bp.route("/packages/<author>/<name>/remove/", methods=["GET", "POST"])
@ -395,7 +395,7 @@ def remove(package):
if "delete" in request.form:
if not package.checkPerm(current_user, Permission.DELETE_PACKAGE):
flash("You don't have permission to do that.", "danger")
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
package.state = PackageState.DELETED
@ -411,19 +411,19 @@ def remove(package):
elif "unapprove" in request.form:
if not package.checkPerm(current_user, Permission.UNAPPROVE_PACKAGE):
flash("You don't have permission to do that.", "danger")
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
package.state = PackageState.WIP
msg = "Unapproved {}".format(package.title)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_APPROVAL, msg, package.getDetailsURL(), package)
addAuditLog(AuditSeverity.EDITOR, current_user, msg, package.getDetailsURL(), package)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_APPROVAL, msg, package.getURL("packages.view"), package)
addAuditLog(AuditSeverity.EDITOR, current_user, msg, package.getURL("packages.view"), package)
db.session.commit()
flash("Unapproved package", "success")
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
else:
abort(400)
@ -440,7 +440,7 @@ class PackageMaintainersForm(FlaskForm):
def edit_maintainers(package):
if not package.checkPerm(current_user, Permission.EDIT_MAINTAINERS):
flash("You do not have permission to edit maintainers", "danger")
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
form = PackageMaintainersForm(formdata=request.form)
if request.method == "GET":
@ -457,12 +457,12 @@ def edit_maintainers(package):
if thread:
thread.watchers.append(user)
addNotification(user, current_user, NotificationType.MAINTAINER,
"Added you as a maintainer of {}".format(package.title), package.getDetailsURL(), package)
"Added you as a maintainer of {}".format(package.title), package.getURL("packages.view"), package)
for user in package.maintainers:
if user != package.author and not user in users:
addNotification(user, current_user, NotificationType.MAINTAINER,
"Removed you as a maintainer of {}".format(package.title), package.getDetailsURL(), package)
"Removed you as a maintainer of {}".format(package.title), package.getURL("packages.view"), package)
package.maintainers.clear()
package.maintainers.extend(users)
@ -470,13 +470,13 @@ def edit_maintainers(package):
package.maintainers.append(package.author)
msg = "Edited {} maintainers".format(package.title)
addNotification(package.author, current_user, NotificationType.MAINTAINER, msg, package.getDetailsURL(), package)
addNotification(package.author, current_user, NotificationType.MAINTAINER, msg, package.getURL("packages.view"), package)
severity = AuditSeverity.NORMAL if current_user == package.author else AuditSeverity.MODERATION
addAuditLog(severity, current_user, msg, package.getDetailsURL(), package)
addAuditLog(severity, current_user, msg, package.getURL("packages.view"), package)
db.session.commit()
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
users = User.query.filter(User.rank >= UserRank.NEW_MEMBER).order_by(db.asc(User.username)).all()
@ -498,11 +498,11 @@ def remove_self_maintainers(package):
package.maintainers.remove(current_user)
addNotification(package.author, current_user, NotificationType.MAINTAINER,
"Removed themself as a maintainer of {}".format(package.title), package.getDetailsURL(), package)
"Removed themself as a maintainer of {}".format(package.title), package.getURL("packages.view"), package)
db.session.commit()
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
@bp.route("/packages/<author>/<name>/audit/")
@ -556,7 +556,7 @@ def alias_create_edit(package: Package, alias_id: int = None):
form.populate_obj(alias)
db.session.commit()
return redirect(package.getAliasListURL())
return redirect(package.getURL("packages.alias_list"))
return render_template("packages/alias_create_edit.html", package=package, form=form)

@ -75,7 +75,7 @@ class EditPackageReleaseForm(FlaskForm):
@is_package_page
def create_release(package):
if not package.checkPerm(current_user, Permission.MAKE_RELEASE):
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
# Initial form class from post data and default data
form = CreatePackageReleaseForm()
@ -144,7 +144,7 @@ def edit_release(package, id):
canEdit = package.checkPerm(current_user, Permission.MAKE_RELEASE)
canApprove = release.checkPerm(current_user, Permission.APPROVE_RELEASE)
if not (canEdit or canApprove):
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
# Initial form class from post data and default data
form = EditPackageReleaseForm(formdata=request.form, obj=release)
@ -171,7 +171,7 @@ def edit_release(package, id):
release.approved = False
db.session.commit()
return redirect(package.getReleaseListURL())
return redirect(package.getURL("packages.list_releases"))
return render_template("packages/release_edit.html", package=package, release=release, form=form)
@ -193,7 +193,7 @@ class BulkReleaseForm(FlaskForm):
@is_package_page
def bulk_change_release(package):
if not package.checkPerm(current_user, Permission.MAKE_RELEASE):
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
# Initial form class from post data and default data
form = BulkReleaseForm()
@ -211,7 +211,7 @@ def bulk_change_release(package):
db.session.commit()
return redirect(package.getReleaseListURL())
return redirect(package.getURL("packages.list_releases"))
return render_template("packages/release_bulk_change.html", package=package, form=form)
@ -225,12 +225,12 @@ def delete_release(package, id):
abort(404)
if not release.checkPerm(current_user, Permission.DELETE_RELEASE):
return redirect(release.getReleaseListURL())
return redirect(package.getURL("packages.list_releases"))
db.session.delete(release)
db.session.commit()
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
class PackageUpdateConfigFrom(FlaskForm):
@ -279,7 +279,7 @@ def update_config(package):
if not package.repo:
flash("Please add a Git repository URL in order to set up automatic releases", "danger")
return redirect(package.getEditURL())
return redirect(package.getURL("packages.create_edit"))
form = PackageUpdateConfigFrom(obj=package.update_config)
if request.method == "GET":
@ -303,9 +303,9 @@ def update_config(package):
if not form.disable.data and package.releases.count() == 0:
flash("Now, please create an initial release", "success")
return redirect(package.getCreateReleaseURL())
return redirect(package.getURL("packages.create_release"))
return redirect(package.getReleaseListURL())
return redirect(package.getURL("packages.list_releases"))
return render_template("packages/update_config.html", package=package, form=form)
@ -318,7 +318,7 @@ def setup_releases(package):
abort(403)
if package.update_config:
return redirect(package.getUpdateConfigURL())
return redirect(package.getURL("packages.update_config"))
return render_template("packages/release_wizard.html", package=package)

@ -46,7 +46,7 @@ class ReviewForm(FlaskForm):
def review(package):
if current_user in package.maintainers:
flash("You can't review your own package!", "danger")
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
review = PackageReview.query.filter_by(package=package, author=current_user).first()
@ -110,7 +110,7 @@ def review(package):
db.session.commit()
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
return render_template("packages/review_create_edit.html",
form=form, package=package, review=review)

@ -50,10 +50,10 @@ class EditPackageScreenshotsForm(FlaskForm):
@is_package_page
def screenshots(package):
if not package.checkPerm(current_user, Permission.ADD_SCREENSHOTS):
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
if package.screenshots.count() == 0:
return redirect(package.getNewScreenshotURL())
return redirect(package.getURL("packages.create_screenshot"))
form = EditPackageScreenshotsForm(obj=package)
form.cover_image.query = package.screenshots
@ -63,7 +63,7 @@ def screenshots(package):
if order:
try:
do_order_screenshots(current_user, package, order.split(","))
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
except LogicError as e:
flash(e.message, "danger")
@ -80,14 +80,14 @@ def screenshots(package):
@is_package_page
def create_screenshot(package):
if not package.checkPerm(current_user, Permission.ADD_SCREENSHOTS):
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
# Initial form class from post data and default data
form = CreateScreenshotForm()
if form.validate_on_submit():
try:
do_create_screenshot(current_user, package, form.title.data, form.fileUpload.data)
return redirect(package.getEditScreenshotsURL())
return redirect(package.getURL("packages.screenshots"))
except LogicError as e:
flash(e.message, "danger")
@ -105,7 +105,7 @@ def edit_screenshot(package, id):
canEdit = package.checkPerm(current_user, Permission.ADD_SCREENSHOTS)
canApprove = package.checkPerm(current_user, Permission.APPROVE_SCREENSHOT)
if not (canEdit or canApprove):
return redirect(package.getEditScreenshotsURL())
return redirect(package.getURL("packages.screenshots"))
# Initial form class from post data and default data
form = EditScreenshotForm(obj=screenshot)
@ -121,7 +121,7 @@ def edit_screenshot(package, id):
screenshot.approved = wasApproved
db.session.commit()
return redirect(package.getEditScreenshotsURL())
return redirect(package.getURL("packages.screenshots"))
return render_template("packages/screenshot_edit.html", package=package, screenshot=screenshot, form=form)
@ -145,4 +145,4 @@ def delete_screenshot(package, id):
db.session.delete(screenshot)
db.session.commit()
return redirect(package.getEditScreenshotsURL())
return redirect(package.getURL("packages.screenshots"))

@ -296,7 +296,7 @@ def new():
flash("Please wait before opening another thread", "danger")
if package:
return redirect(package.getDetailsURL())
return redirect(package.getURL("packages.view"))
else:
return redirect(url_for("homepage.home"))

@ -221,8 +221,8 @@ def apply_all_updates(username):
msg = "Created release {} (Applied all Git Update Detection)".format(rel.title)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_EDIT, msg,
rel.getEditURL(), package)
addAuditLog(AuditSeverity.NORMAL, current_user, msg, package.getDetailsURL(), package)
rel.getURL("packages.create_edit"), package)
addAuditLog(AuditSeverity.NORMAL, current_user, msg, package.getURL("packages.view"), package)
db.session.commit()
return redirect(url_for("todo.view_user", username=username))

@ -176,7 +176,7 @@ def do_edit_package(user: User, package: Package, was_new: bool, was_web: bool,
msg = "Edited {} ({})".format(package.title, reason)
severity = AuditSeverity.NORMAL if user in package.maintainers else AuditSeverity.EDITOR
addAuditLog(severity, user, msg, package.getDetailsURL(), package)
addAuditLog(severity, user, msg, package.getURL("packages.view"), package)
db.session.commit()

@ -53,7 +53,7 @@ def do_create_vcs_release(user: User, package: Package, title: str, ref: str,
msg = "Created release {}".format(rel.title)
else:
msg = "Created release {} ({})".format(rel.title, reason)
addAuditLog(AuditSeverity.NORMAL, user, msg, package.getDetailsURL(), package)
addAuditLog(AuditSeverity.NORMAL, user, msg, package.getURL("packages.view"), package)
db.session.commit()
@ -88,7 +88,7 @@ def do_create_zip_release(user: User, package: Package, title: str, file,
msg = "Created release {}".format(rel.title)
else:
msg = "Created release {} ({})".format(rel.title, reason)
addAuditLog(AuditSeverity.NORMAL, user, msg, package.getDetailsURL(), package)
addAuditLog(AuditSeverity.NORMAL, user, msg, package.getURL("packages.view"), package)
db.session.commit()

@ -32,8 +32,8 @@ def do_create_screenshot(user: User, package: Package, title: str, file, reason:
else:
msg = "Created screenshot {} ({})".format(ss.title, reason)
addNotification(package.maintainers, user, NotificationType.PACKAGE_EDIT, msg, package.getDetailsURL(), package)
addAuditLog(AuditSeverity.NORMAL, user, msg, package.getDetailsURL(), package)
addNotification(package.maintainers, user, NotificationType.PACKAGE_EDIT, msg, package.getURL("packages.view"), package)
addAuditLog(AuditSeverity.NORMAL, user, msg, package.getURL("packages.view"), package)
db.session.commit()

@ -435,7 +435,7 @@ class Package(db.Model):
"thumbnail": (base_url + tnurl) if tnurl is not None else None,
"screenshots": [base_url + ss.url for ss in self.screenshots],
"url": base_url + self.getDownloadURL(),
"url": base_url + self.getURL("packages.download"),
"release": release and release.id,
"score": round(self.score * 10) / 10,
@ -460,17 +460,12 @@ class Package(db.Model):
else:
return screenshot.url
def getURL(self, endpoint):
return url_for(endpoint, author=self.author.username, name=self.name)
def getDetailsURL(self, absolute=False):
def getURL(self, endpoint, absolute=False, **kwargs):
if absolute:
from app.utils import abs_url_for
return abs_url_for("packages.view",
author=self.author.username, name=self.name)
return abs_url_for(endpoint, author=self.author.username, name=self.name, **kwargs)
else:
return url_for("packages.view",
author=self.author.username, name=self.name)
return url_for(endpoint, author=self.author.username, name=self.name, **kwargs)
def getShieldURL(self, type):
from app.utils import abs_url_for
@ -479,15 +474,7 @@ class Package(db.Model):
def makeShield(self, type):
return "[![ContentDB]({})]({})" \
.format(self.getShieldURL(type), self.getDetailsURL(True))
def getEditURL(self):
return url_for("packages.create_edit",
author=self.author.username, name=self.name)
def getReleaseListURL(self):
return url_for("packages.list_releases",
author=self.author.username, name=self.name)
.format(self.getShieldURL(type), self.getURL("packages.view", True))
def getSetStateURL(self, state):
if type(state) == str:
@ -498,54 +485,6 @@ class Package(db.Model):
return url_for("packages.move_to_state",
author=self.author.username, name=self.name, state=state.name.lower())
def getRemoveURL(self):
return url_for("packages.remove",
author=self.author.username, name=self.name)
def getNewScreenshotURL(self):
return url_for("packages.create_screenshot",
author=self.author.username, name=self.name)
def getEditScreenshotsURL(self):
return url_for("packages.screenshots",
author=self.author.username, name=self.name)
def getCreateReleaseURL(self, **kwargs):
return url_for("packages.create_release",
author=self.author.username, name=self.name, **kwargs)
def getBulkReleaseURL(self):
return url_for("packages.bulk_change_release",
author=self.author.username, name=self.name)
def getUpdateConfigURL(self, trigger=None, action=None):
return url_for("packages.update_config",
author=self.author.username, name=self.name, trigger=trigger, action=action)
def getSetupReleasesURL(self):
return url_for("packages.setup_releases",
author=self.author.username, name=self.name)
def getDownloadURL(self):
return url_for("packages.download",
author=self.author.username, name=self.name)
def getEditMaintainersURL(self):
return url_for("packages.edit_maintainers",
author=self.author.username, name=self.name)
def getRemoveSelfMaintainerURL(self):
return url_for("packages.remove_self_maintainers",
author=self.author.username, name=self.name)
def getReviewURL(self, external=False):
return url_for('packages.review', _external=external,
author=self.author.username, name=self.name)
def getAuditLogURL(self):
return url_for('packages.audit',
author=self.author.username, name=self.name)
def getDownloadRelease(self, version=None):
for rel in self.releases:
if rel.approved and (version is None or
@ -555,14 +494,6 @@ class Package(db.Model):
return None
def getAliasListURL(self):
return url_for("packages.alias_list",
author=self.author.username, name=self.name)
def getAliasCreateURL(self):
return url_for("packages.alias_create_edit",
author=self.author.username, name=self.name)
def checkPerm(self, user, perm):
if not user.is_authenticated:
return False
@ -1049,7 +980,7 @@ class PackageUpdateConfig(db.Model):
return self.last_tag or self.last_commit
def get_create_release_url(self):
return self.package.getCreateReleaseURL(title=self.get_title(), ref=self.get_ref())
return self.package.getURL("packages.create_release", title=self.get_title(), ref=self.get_ref())
class PackageAlias(db.Model):

@ -150,7 +150,7 @@ class PackageReview(db.Model):
return 1 if self.recommends else -1
def getEditURL(self):
return self.package.getReviewURL()
return self.package.getURL("packages.review")
def getDeleteURL(self):
return url_for("packages.delete_review",

@ -262,7 +262,7 @@ def check_update_config_impl(package):
db.session.add(rel)
msg = "Created release {} (Git Update Detection)".format(rel.title)
addSystemAuditLog(AuditSeverity.NORMAL, msg, package.getDetailsURL(), package)
addSystemAuditLog(AuditSeverity.NORMAL, msg, package.getURL("packages.view"), package)
db.session.commit()
@ -320,7 +320,7 @@ def check_update_config(self, package_id):
.strip()
msg = "Error: {}.\n\nTask ID: {}\n\n[Change update configuration]({})" \
.format(err, self.request.id, package.getUpdateConfigURL())
.format(err, self.request.id, package.getURL("packages.update_config"))
post_bot_message(package, "Failed to check git repository", msg)

@ -32,7 +32,7 @@
{% set cover_image = package.cover_image.url or package.getMainScreenshotURL() %}
{% set tags = package.tags | sort(attribute="views", reverse=True) %}
<div class="carousel-item {% if loop.index == 1 %}active{% endif %}">
<a href="{{ package.getDetailsURL() }}">
<a href="{{ package.getURL("packages.view") }}">
<div class="embed-responsive embed-responsive-16by9">
<img class="embed-responsive-item" src="{{ cover_image }}"
alt="{{ _('%(title)s by %(author)s', title=package.title, author=package.author.display_name) }}">

@ -18,9 +18,9 @@
{% set message %}
{% if package.checkPerm(current_user, "MAKE_RELEASE") %}
{% if package.update_config %}
<a class="btn btn-sm btn-warning float-right" href="{{ package.getCreateReleaseURL() }}">Create first release</a>
<a class="btn btn-sm btn-warning float-right" href="{{ package.getURL("packages.create_release") }}">Create first release</a>
{% else %}
<a class="btn btn-sm btn-warning float-right" href="{{ package.getSetupReleasesURL() }}">Set up releases</a>
<a class="btn btn-sm btn-warning float-right" href="{{ package.getURL("packages.setup_releases") }}">Set up releases</a>
{% endif %}
{{ _("You need to create a release before this package can be approved.") }}
{% else %}

@ -1,5 +1,5 @@
{% macro render_pkgtile(package, show_author) -%}
<li class="packagetile flex-fill"><a href="{{ package.getDetailsURL() }}"
<li class="packagetile flex-fill"><a href="{{ package.getURL("packages.view") }}"
style="background-image: url({{ package.getThumbnailOrPlaceholder(2) }});">
<div class="packagegridscrub"></div>
<div class="packagegridinfo">

@ -88,7 +88,7 @@
created {{ rel.releaseDate | date }}.
</small>
{% if (package.checkPerm(current_user, "MAKE_RELEASE") or rel.checkPerm(current_user, "APPROVE_RELEASE")) and rel.task_id %}
<a href="{{ url_for('tasks.check', id=rel.task_id, r=package.getDetailsURL()) }}">Importing...</a>
<a href="{{ url_for('tasks.check', id=rel.task_id, r=package.getURL("packages.view")) }}">Importing...</a>
{% elif not rel.approved %}
Waiting for approval.
{% endif %}

@ -33,7 +33,7 @@
<div class="card-body markdown">
{% if current_user == review.author %}
<a class="btn btn-primary btn-sm ml-1 float-right"
href="{{ review.package.getReviewURL() }}">
href="{{ review.package.getURL("packages.review") }}">
<i class="fas fa-pen"></i>
</a>
{% endif %}
@ -46,7 +46,7 @@
<p class="mt-2 mb-0">
{% if show_package_link %}
<a class="btn btn-primary mr-1" href="{{ review.package.getDetailsURL() }}">
<a class="btn btn-primary mr-1" href="{{ review.package.getURL("packages.view") }}">
{{ _("%(title)s by %(author)s",
title="<b>" | safe + review.package.title + "</b>" | safe,
author=review.package.author.display_name) }}
@ -78,7 +78,7 @@
<div class="card-header">
{{ _("Review") }}
</div>
<form method="post" action="{{ package.getReviewURL() }}" class="card-body">
<form method="post" action="{{ package.getURL("packages.review") }}" class="card-body">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<p>
{{ _("Do you recommend this %(type)s?", type=package.type.value | lower) }}
@ -117,7 +117,7 @@
<div class="card-header">
{{ _("Review") }}
</div>
<form method="post" action="{{ package.getReviewURL() }}" class="card-body">
<form method="post" action="{{ package.getURL("packages.review") }}" class="card-body">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<p>
{{ _("Do you recommend this %(type)s?", type=package.type.value | lower) }}

@ -49,7 +49,7 @@
{% if current_user == thread.author and thread.review and thread.replies[0] == r %}
<a class="float-right btn btn-primary btn-sm ml-2"
href="{{ thread.review.package.getReviewURL() }}">
href="{{ thread.review.package.getURL("packages.review") }}">
<i class="fas fa-pen"></i>
</a>
{% elif r.checkPerm(current_user, "EDIT_REPLY") %}

@ -5,7 +5,7 @@
<li class="list-group-item">
<div class="row">
{% if package %}
<a class="col-sm-auto text-muted" style="min-width: 200px;" href="{{ package.getDetailsURL() }}">
<a class="col-sm-auto text-muted" style="min-width: 200px;" href="{{ package.getURL("packages.view") }}">
<img
class="img-fluid"
style="max-height: 22px; max-width: 22px;"
@ -45,7 +45,7 @@
</a>
{% if package.checkPerm(current_player, "MAKE_RELEASE") %}
<a class="btn btn-sm btn-secondary" href="{{ package.getUpdateConfigURL() }}">
<a class="btn btn-sm btn-secondary" href="{{ package.getURL("packages.update_config") }}">
<i class="fas fa-cog mr-1"></i>
{{ _("Update settings") }}
</a>

@ -5,11 +5,11 @@
{% endblock %}
{% block link %}
<a href="{{ package.getDetailsURL() }}">{{ package.title }}</a>
<a href="{{ package.getURL("packages.view") }}">{{ package.title }}</a>
{% endblock %}
{% block content %}
<a class="btn btn-secondary" href="{{ package.getAliasListURL() }}">Back to Aliases</a>
<a class="btn btn-secondary" href="{{ package.getURL("packages.alias_list") }}">Back to Aliases</a>
{% from "macros/forms.html" import render_field, render_submit_field, render_toggle_field %}
<form method="POST" action="" enctype="multipart/form-data" class="mt-4">

@ -5,11 +5,11 @@
{% endblock %}
{% block link %}
<a href="{{ package.getDetailsURL() }}">{{ package.title }}</a>
<a href="{{ package.getURL("packages.view") }}">{{ package.title }}</a>
{% endblock %}
{% block content %}
<a class="btn btn-primary float-right" href="{{ package.getAliasCreateURL() }}">Create</a>
<a class="btn btn-primary float-right" href="{{ package.getURL("packages.alias_create_edit") }}">Create</a>
<h1>{{ _("Aliases for %(title)s by %(author)s", title=self.link(), author=package.author.display_name) }}</h1>
<div class="list-group">

@ -6,7 +6,7 @@
<div class="row">
<div class="col-md-3 mb-4">
<div class="list-group">
<a class="list-group-item list-group-item-action" href="{{ package.getDetailsURL() }}">
<a class="list-group-item list-group-item-action" href="{{ package.getURL("packages.view") }}">
<span class="row m-0 p-0">
<span class="col-auto m-0 p-0">
<img class="img-fluid user-photo img-thumbnail img-thumbnail-1"

@ -9,7 +9,7 @@
{% if package.update_config %}
<p class="alert alert-secondary mb-4">
<a class="float-right btn btn-sm btn-secondary" href="{{ package.getUpdateConfigURL() }}">{{ _("Settings") }}</a>
<a class="float-right btn btn-sm btn-secondary" href="{{ package.getURL("packages.update_config") }}">{{ _("Settings") }}</a>
{% if package.update_config.make_release %}
{{ _("You have automatic releases enabled.") }}
{% else %}
@ -20,12 +20,12 @@
{% else %}
<p class="alert alert-info mb-4">
{% if package.repo %}
<a class="float-right btn btn-sm btn-info" href="{{ package.getSetupReleasesURL() }}">{{ _("Set up") }}</a>
<a class="float-right btn btn-sm btn-info" href="{{ package.getURL("packages.setup_releases") }}">{{ _("Set up") }}</a>
<i class="fas fa-info mr-2"></i>
{{ _("You can create releases automatically when you push commits or tags to your repository.") }}
{% else %}
<a class="float-right btn btn-sm btn-info" href="{{ package.getEditURL() }}">{{ _("Add Git repo") }}</a>
<a class="float-right btn btn-sm btn-info" href="{{ package.getURL("packages.create_edit") }}">{{ _("Add Git repo") }}</a>
<i class="fas fa-info mr-2"></i>
{{ _("Using Git would allow you to create releases automatically when you push code or tags.") }}

@ -5,7 +5,7 @@
{% endblock %}
{% block content %}
<a class="btn btn-secondary float-right" href="{{ package.getDetailsURL() }}">
<a class="btn btn-secondary float-right" href="{{ package.getURL("packages.view") }}">
{{ _("Later") }}
</a>
<h1>{{ self.title() }}</h1>
@ -30,13 +30,13 @@
<div class="col-md-6 mt-5">
<h3 class="mt-0">{{ _("Automatically (Recommended)") }}</h3>
<p>
<a class="btn btn-primary" href="{{ package.getUpdateConfigURL(trigger="commit") }}">
<a class="btn btn-primary" href="{{ package.getURL("packages.update_config", trigger="commit") }}">
{{ _("Rolling Release") }}
</a>
<a class="btn btn-primary ml-2" href="{{ package.getUpdateConfigURL(trigger="tag") }}">
<a class="btn btn-primary ml-2" href="{{ package.getURL("packages.update_config", trigger="tag") }}">
{{ _("On Git Tag") }}
</a>
{# <a class="btn btn-secondary ml-2" href="{{ package.getUpdateConfigURL() }}">#}
{# <a class="btn btn-secondary ml-2" href="{{ package.getURL("packages.update_config") }}">#}
{# {{ _("Advanced") }}#}
{# </a>#}
</p>
@ -45,10 +45,10 @@
<div class="col-md-6 mt-5">
<h3 class="mt-0">{{ _("Manually") }}</h3>
<p>
<a class="btn btn-secondary" href="{{ package.getUpdateConfigURL(action="notification") }}">
<a class="btn btn-secondary" href="{{ package.getURL("packages.update_config", action="notification") }}">
{{ _("With reminders") }}
</a>
<a class="btn btn-secondary ml-2" href="{{ package.getCreateReleaseURL() }}">
<a class="btn btn-secondary ml-2" href="{{ package.getURL("packages.create_release") }}">
{{ _("No reminders") }}
</a>
</p>
@ -65,9 +65,9 @@
</p>
<p class="mt-5">
<a class="btn btn-primary" href="{{ package.getEditURL() }}">Add Git repo</a>
<a class="btn btn-secondary ml-2" href="{{ package.getCreateReleaseURL() }}">Create releases manually</a>
<a class="btn btn-secondary ml-2" href="{{ package.getDetailsURL() }}">Later</a>
<a class="btn btn-primary" href="{{ package.getURL("packages.create_edit") }}">Add Git repo</a>
<a class="btn btn-secondary ml-2" href="{{ package.getURL("packages.create_release") }}">Create releases manually</a>
<a class="btn btn-secondary ml-2" href="{{ package.getURL("packages.view") }}">Later</a>
</p>
{% endif %}
{% endblock %}

@ -8,23 +8,23 @@
{% if package.checkPerm(current_user, "MAKE_RELEASE") %}
<p class="float-right">
{% if package.update_config %}
<a class="btn btn-secondary" href="{{ package.getUpdateConfigURL() }}">
<a class="btn btn-secondary" href="{{ package.getURL("packages.update_config") }}">
<i class="fas fa-cog mr-1"></i>
{{ _("Update settings") }}
</a>
{% elif package.repo %}
<a class="btn btn-secondary" href="{{ package.getSetupReleasesURL() }}">
<a class="btn btn-secondary" href="{{ package.getURL("packages.setup_releases") }}">
<i class="fas fa-hat-wizard mr-1"></i>
{{ _("Set up automatic releases") }}
</a>
{% endif %}
<a class="btn btn-secondary ml-1" href="{{ package.getBulkReleaseURL() }}">
<a class="btn btn-secondary ml-1" href="{{ package.getURL("packages.bulk_change_release") }}">
<i class="fas fa-wrench mr-1"></i>
Bulk update
</a>
<a class="btn btn-primary ml-1" href="{{ package.getCreateReleaseURL() }}">
<a class="btn btn-primary ml-1" href="{{ package.getURL("packages.create_release") }}">
<i class="fas fa-plus mr-1"></i>
Create
</a>

@ -23,7 +23,7 @@ Remove {{ package.title }}
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<a class="btn btn-secondary float-right" href="{{ package.getDetailsURL() }}">Cancel</a>
<a class="btn btn-secondary float-right" href="{{ package.getURL("packages.view") }}">Cancel</a>
<input type="submit" name="delete" value="Remove" class="btn btn-danger mr-2" />

@ -5,7 +5,7 @@
{% endblock %}
{% block link %}
<a href="{{ package.getDetailsURL() }}">{{ package.title }}</a>
<a href="{{ package.getURL("packages.view") }}">{{ package.title }}</a>
{% endblock %}
{% block content %}

@ -6,7 +6,7 @@
{% block content %}
{% if package.checkPerm(current_user, "ADD_SCREENSHOTS") %}
<a href="{{ package.getNewScreenshotURL() }}" class="btn btn-primary float-right">
<a href="{{ package.getURL("packages.create_screenshot") }}" class="btn btn-primary float-right">
<i class="fas fa-plus mr-1"></i>
{{ _("Add Image") }}
</a>

@ -13,7 +13,7 @@ Share and Badges
Review link:
</p>
<pre><code>{{ package.getReviewURL(external=True) }}</code></pre>
<pre><code>{{ package.getURL("packages.review", absolute=True) }}</code></pre>
<h3>Badges</h3>

@ -10,7 +10,7 @@
<meta name="og:title" content="{{ package.title }}"/>
<meta name="og:description" content="{{ package.short_desc }}"/>
<meta name="description" content="{{ package.short_desc }}"/>
<meta name="og:url" content="{{ package.getDetailsURL(absolute=True) }}"/>
<meta name="og:url" content="{{ package.getURL("packages.view", absolute=True) }}"/>
{% if package.getMainScreenshotURL() %}
<meta name="og:image" content="{{ package.getMainScreenshotURL(absolute=True) }}"/>
{% endif %}
@ -35,19 +35,19 @@
<div class="container">
<div class="btn-group float-right mb-4">
{% if package.checkPerm(current_user, "EDIT_PACKAGE") %}
<a class="btn btn-primary" href="{{ package.getEditURL() }}">
<a class="btn btn-primary" href="{{ package.getURL("packages.create_edit") }}">
<i class="fas fa-pen mr-1"></i>
{{ _("Edit") }}
</a>
{% endif %}
{% if package.checkPerm(current_user, "MAKE_RELEASE") %}
<a class="btn btn-primary" href="{{ package.getCreateReleaseURL() }}">
<a class="btn btn-primary" href="{{ package.getURL("packages.create_release") }}">
<i class="fas fa-plus mr-1"></i>
{{ _("Release") }}
</a>
{% endif %}
{% if package.checkPerm(current_user, "DELETE_PACKAGE") or package.checkPerm(current_user, "UNAPPROVE_PACKAGE") %}
<a class="btn btn-danger" href="{{ package.getRemoveURL() }}">
<a class="btn btn-danger" href="{{ package.getURL("packages.remove") }}">
<i class="fas fa-trash mr-1"></i>
{{ _("Remove") }}
</a>
@ -94,7 +94,7 @@
</span>
</a>
{% if release %}
<a class="btn" rel="nofollow" href="{{ package.getDownloadURL() }}" title="{{ _("Downloads") }}"
<a class="btn" rel="nofollow" href="{{ package.getURL("packages.download") }}" title="{{ _("Downloads") }}"
download="{{ release.getDownloadFileName() }}">
<i class="fas fa-download"></i>
<span class="count">{{ package.downloads }}</span>
@ -154,7 +154,7 @@
<div class="btn-group btn-group-horizontal col-md-auto">
{% if release %}
<a class="btn btn-download" rel="nofollow" download="{{ release.getDownloadFileName() }}"
href="{{ package.getDownloadURL() }}">
href="{{ package.getURL("packages.download") }}">
{{ _("Download") }}
</a>
{% if package.type == package.type.MOD %}
@ -209,7 +209,7 @@
{% set screenshots = package.screenshots.all() %}
{% if screenshots or package.checkPerm(current_user, "ADD_SCREENSHOTS") %}
{% if package.checkPerm(current_user, "ADD_SCREENSHOTS") %}
<a href="{{ package.getEditScreenshotsURL() }}" class="btn btn-primary float-right">
<a href="{{ package.getURL("packages.screenshots") }}" class="btn btn-primary float-right">
<i class="fas fa-images mr-1"></i>
Edit
</a>
@ -229,7 +229,7 @@
{% endif %}
{% else %}
<li>
<a href="{{ package.getNewScreenshotURL() }}">
<a href="{{ package.getURL("packages.create_screenshot") }}">
<i class="fas fa-plus screenshot-add"></i>
</a>
</li>
@ -249,7 +249,7 @@
{% if current_user.is_authenticated %}
{% if has_review %}
<p>
<a class="btn btn-primary" href="{{ package.getReviewURL() }}">
<a class="btn btn-primary" href="{{ package.getURL("packages.review") }}">
{{ _("Edit Review") }}
</a>
</p>
@ -307,7 +307,7 @@
<i class="fas fa-plus mr-1"></i>
{{ _("Release") }}
</a>
<a class="btn btn-warning" href="{{ package.getUpdateConfigURL() }}">
<a class="btn btn-warning" href="{{ package.getURL("packages.update_config") }}">
<i class="fas fa-cog mr-1"></i>
{{ _("Update settings") }}
</a>
@ -329,7 +329,7 @@
{% for dep in package.getSortedHardDependencies() %}
{%- if dep.package %}
<a class="badge badge-primary"
href="{{ dep.package.getDetailsURL() }}">
href="{{ dep.package.getURL("packages.view") }}">
{{ dep.package.title }} by {{ dep.package.author.display_name }}
</a>
{% elif dep.meta_package %}
@ -352,7 +352,7 @@
{% for dep in optional_deps %}
{%- if dep.package %}
<a class="badge badge-secondary"
href="{{ dep.package.getDetailsURL() }}">
href="{{ dep.package.getURL("packages.view") }}">
{{ dep.package.title }} by {{ dep.package.author.display_name }}
{% elif dep.meta_package %}
<a class="badge badge-secondary"
@ -399,7 +399,7 @@
{% endfor %}
{% if current_user in package.maintainers and current_user != package.author %}
<form class="mt-2" method="post" action="{{ package.getRemoveSelfMaintainerURL() }}">
<form class="mt-2" method="post" action="{{ package.getURL("packages.remove_self_maintainers") }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input class="btn btn-sm btn-link p-0" type="submit" value="{{ _('Remove myself') }}" />
</form>
@ -422,7 +422,7 @@
<h3>
{% if package.checkPerm(current_user, "MAKE_RELEASE") %}
<a class="btn btn-primary btn-sm float-right" href="{{ package.getCreateReleaseURL() }}"><i class="fas fa-plus"></i></a>
<a class="btn btn-primary btn-sm float-right" href="{{ package.getURL("packages.create_release") }}"><i class="fas fa-plus"></i></a>
{% endif %}
{{ _("Releases") }}
</h3>
@ -433,7 +433,7 @@
{% else %}
{{ render_releases_download(releases, package) }}
{% endif %}
<a class="list-group-item list-group-item-action text-center py-1 text-muted" href="{{ package.getReleaseListURL() }}">
<a class="list-group-item list-group-item-action text-center py-1 text-muted" href="{{ package.getURL("packages.list_releases") }}">
More
</a>
</div>
@ -459,7 +459,7 @@
</a>
{% endif %}
{% if package.checkPerm(current_user, "EDIT_PACKAGE") %}
<a class="float-right" href="{{ package.getAuditLogURL() }}">
<a class="float-right" href="{{ package.getURL("packages.audit") }}">
See audit log
</a>
{% endif %}

@ -37,7 +37,7 @@
{% if current_user == thread.author and thread.review %}
<a class="btn btn-primary ml-1 float-right mr-2"
href="{{ thread.review.package.getReviewURL() }}">
href="{{ thread.review.package.getURL("packages.review") }}">
<i class="fas fa-pen"></i>
{{ _("Edit Review") }}
</a>
@ -56,7 +56,7 @@
{% if thread.package %}
<p>
Package: <a href="{{ thread.package.getDetailsURL() }}">{{ thread.package.title }}</a>
Package: <a href="{{ thread.package.getURL("packages.view") }}">{{ thread.package.title }}</a>
</p>
{% endif %}

@ -17,7 +17,7 @@
</h3>
<ul class="card-body d-flex p-0 flex-row flex-wrap justify-content-start align-content-start p-4">
{% for s in screenshots %}
<li class="packagetile flex-fill"><a href="{{ s.getEditURL() }}"
<li class="packagetile flex-fill"><a href="{{ s.getURL("packages.create_edit") }}"
style="background-image: url({{ s.getThumbnailURL(3) }});">
<div class="packagegridscrub"></div>
<div class="packagegridinfo">
@ -46,7 +46,7 @@
<h3 class="card-header">Packages</h3>
<div class="list-group list-group-flush">
{% for p in packages %}
<a href="{{ p.getDetailsURL() }}" class="list-group-item list-group-item-action">
<a href="{{ p.getURL("packages.view") }}" class="list-group-item list-group-item-action">
<span class="float-right" title="Created {{ p.created_at | datetime }}">
<small>
{{ p.created_at | timedelta }} ago
@ -83,7 +83,7 @@
{% endif %}
<a href="{{ r.getEditURL() }}">{{ r.title }}</a>
on
<a href="{{ r.package.getDetailsURL() }}">
<a href="{{ r.package.getURL("packages.view") }}">
{{ r.package.title }} by {{ r.package.author.display_name }}
</a>
</li>
@ -139,7 +139,7 @@
<h3 class="card-header">WIP Packages</h3>
<div class="list-group list-group-flush" style="max-height: 300px; overflow: hidden auto;">
{% for p in wip_packages %}
<a href="{{ p.getDetailsURL() }}" class="list-group-item list-group-item-action">
<a href="{{ p.getURL("packages.view") }}" class="list-group-item list-group-item-action">
<span class="float-right" title="Created {{ p.created_at | datetime }}">
<small>
{{ p.created_at | timedelta }} ago

@ -42,7 +42,7 @@
{% for package in packages %}
<tr>
<td>
<a href="{{ package.getDetailsURL() }}">
<a href="{{ package.getURL("packages.view") }}">
{{ package.title }}
</a>
@ -50,7 +50,7 @@
</td>
<td class="text-center">
{% if package.checkPerm(current_user, "EDIT_PACKAGE") %}
<a class="btn btn-link btn-sm py-0" href="{{ package.getEditURL() }}">
<a class="btn btn-link btn-sm py-0" href="{{ package.getURL("packages.create_edit") }}">
<i class="fas fa-pen"></i>
</a>
{% endif %}

@ -8,7 +8,7 @@
<h2>{{ _("Unapproved Packages Needing Action") }}</h2>
<div class="list-group mt-3 mb-5">
{% for package in unapproved_packages %}
<a class="list-group-item list-group-item-action" href="{{ package.getDetailsURL() }}">
<a class="list-group-item list-group-item-action" href="{{ package.getURL("packages.view") }}">
<div class="row">
<div class="col-sm-2 text-muted">
<img
@ -62,7 +62,7 @@
</p>
<div class="list-group mt-3 mb-5">
{% for package in needs_tags %}
<a class="list-group-item list-group-item-action" href="{{ package.getDetailsURL() }}">
<a class="list-group-item list-group-item-action" href="{{ package.getURL("packages.view") }}">
<img
class="img-fluid"
style="max-height: 22px; max-width: 22px;"