-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #13638: Utilize {% querystring %} template tag for pagination #13910
Open
BrendenBrahier
wants to merge
2
commits into
WeblateOrg:main
Choose a base branch
from
BrendenBrahier:issue-13638
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,95 +1,29 @@ | ||
{% load i18n %} | ||
{% load icons %} | ||
{% load querystring %} | ||
|
||
{% if page_obj.paginator.num_pages > 1 %} | ||
<ul class="pagination"> | ||
<li {% if page_obj.number == 1 %}class="disabled"{% endif %}> | ||
<a href="?page=1&limit={{ page_obj.paginator.per_page }}{% if page_obj.paginator.sort_by %}&sort_by={{ page_obj.paginator.sort_by }}{% endif %}{% if query_string %}&{{ query_string }}{% endif %}{% if anchor %}#{{ anchor }}{% endif %}" | ||
class="green"> | ||
{% if LANGUAGE_BIDI %} | ||
{% icon "page-last.svg" %} | ||
{% else %} | ||
{% icon "page-first.svg" %} | ||
{% endif %} | ||
</a> | ||
</li> | ||
<li {% if not page_obj.has_previous %}class="disabled"{% endif %}> | ||
<a | ||
{% if page_obj.has_previous %} | ||
rel="prev" | ||
{# djlint:off #} | ||
href="?page={{ page_obj.previous_page_number }}&limit={{ page_obj.paginator.per_page }}{% if page_obj.paginator.sort_by %}&sort_by={{ page_obj.paginator.sort_by }}{% endif %}{% if query_string %}&{{ query_string }}{% endif %}{% if anchor %}#{{ anchor }}{% endif %}" | ||
{# djlint:on #} | ||
{% endif %} | ||
class="green"> | ||
{% if LANGUAGE_BIDI %} | ||
{% icon "page-next.svg" %} | ||
{% else %} | ||
{% icon "page-previous.svg" %} | ||
{% endif %} | ||
</a> | ||
</li> | ||
<li> | ||
<a class="position-input" title="{% trans "Click to edit position" %}"> | ||
{% blocktrans with page_obj.number as position and page_obj.paginator.num_pages as total %}{{ position }} / {{ total }}{% endblocktrans %} | ||
</a> | ||
<a class="position-input-editable" title="{% trans "Go to position" %}"> | ||
{% if not paginator_form %}<form method="get">{% endif %} | ||
{% for key, value in search_items %} | ||
<input {% if paginator_form %}form="{{ paginator_form }}"{% endif %} | ||
type="hidden" | ||
name="{{ key }}" | ||
value="{{ value }}" | ||
aria-label="{{ value }}" /> | ||
{% endfor %} | ||
<input {% if paginator_form %}form="{{ paginator_form }}"{% endif %} | ||
type="hidden" | ||
name="limit" | ||
value="{{ page_obj.paginator.per_page }}" | ||
aria-label="{{ page_obj.paginator.per_page }}" /> | ||
<div class="input-group"> | ||
<input {% if paginator_form %}form="{{ paginator_form }}"{% endif %} | ||
type="number" | ||
min="1" | ||
max="{{ page_obj.paginator.num_pages }}" | ||
name="page" | ||
class="form-control" | ||
value="{{ page_obj.number }}" | ||
aria-label="{% trans "Jump to" %}" | ||
id="position-input-editable-input"> | ||
<span class="input-group-addon"> | ||
{% comment %}Translators: This is partial position indicator shown when editing position{% endcomment %} | ||
{% blocktrans with page_obj.paginator.num_pages as total %}/ {{ total }}{% endblocktrans %} | ||
</span> | ||
</div> | ||
{% if not paginator_form %}</form>{% endif %} | ||
</a> | ||
</li> | ||
<li {% if not page_obj.has_next %}class="disabled"{% endif %}> | ||
<a | ||
{% if page_obj.has_next %} | ||
rel="next" | ||
{# djlint:off #} | ||
href="?page={{ page_obj.next_page_number }}&limit={{ page_obj.paginator.per_page }}{% if page_obj.paginator.sort_by %}&sort_by={{ page_obj.paginator.sort_by }}{% endif %}{% if query_string %}&{{ query_string }}{% endif %}{% if anchor %}#{{ anchor }}{% endif %}" | ||
{# djlint:on #} | ||
{% endif %} | ||
class="green"> | ||
{% if not LANGUAGE_BIDI %} | ||
{% icon "page-next.svg" %} | ||
{% else %} | ||
{% icon "page-previous.svg" %} | ||
{% endif %} | ||
</a> | ||
</li> | ||
<li {% if page_obj.paginator.num_pages == page_obj.number %}class="disabled"{% endif %}> | ||
<a href="?page={{ page_obj.paginator.num_pages }}&limit={{ page_obj.paginator.per_page }}{% if page_obj.paginator.sort_by %}&sort_by={{ page_obj.paginator.sort_by }}{% endif %}{% if query_string %}&{{ query_string }}{% endif %}{% if anchor %}#{{ anchor }}{% endif %}" | ||
class="green"> | ||
{% if not LANGUAGE_BIDI %} | ||
{% icon "page-last.svg" %} | ||
{% else %} | ||
{% icon "page-first.svg" %} | ||
{% endif %} | ||
</a> | ||
</li> | ||
<nav class="pagination"> | ||
<ul> | ||
{% if page_obj.has_previous %} | ||
<li> | ||
<a href="?{% querystring page=page_obj.previous_page_number %}">« Previous</a> | ||
</li> | ||
{% endif %} | ||
|
||
{% for page_number in page_obj.paginator.page_range %} | ||
{% if page_number == page_obj.number %} | ||
<li class="active"> | ||
<span>{{ page_number }}</span> | ||
</li> | ||
{% else %} | ||
<li> | ||
<a href="?{% querystring page=page_number %}">{{ page_number }}</a> | ||
</li> | ||
{% endif %} | ||
{% endfor %} | ||
|
||
{% if page_obj.has_next %} | ||
<li> | ||
<a href="?{% querystring page=page_obj.next_page_number %}">Next »</a> | ||
</li> | ||
{% endif %} | ||
</ul> | ||
{% endif %} | ||
</nav> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,6 @@ | |
{% endif %} | ||
{% endblock %} | ||
|
||
|
||
{% block content %} | ||
|
||
{% if show_results %} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -329,7 +329,7 @@ | |
lang_label, | ||
) | ||
plural = translation.plural | ||
placeables_set = set() | ||
for text in plurals: | ||
placeables_set.update(hl[2] for hl in highlight_string(text, unit)) | ||
placeables = list(placeables_set) | ||
|
@@ -530,7 +530,7 @@ | |
if unit.readonly: | ||
for field in ["target", "fuzzy", "review"]: | ||
self.fields[field].widget.attrs["readonly"] = 1 | ||
self.fields["review"].choices = [ | ||
(state, label) | ||
for state, label in StringState.choices | ||
if state == STATE_READONLY | ||
|
@@ -540,7 +540,7 @@ | |
self.fields["review"].widget.attrs["class"] = "review_radio" | ||
# Avoid failing validation on untranslated string | ||
if args: | ||
self.fields["review"].choices.append((STATE_EMPTY, "")) | ||
self.helper = FormHelper() | ||
self.helper.form_method = "post" | ||
self.helper.form_tag = False | ||
|
@@ -640,7 +640,7 @@ | |
|
||
def __init__(self, translation: Translation, *args, **kwargs) -> None: | ||
super().__init__(*args, **kwargs) | ||
self.fields["format"].choices = [ | ||
(x.name, x.verbose) for x in EXPORTERS.values() if x.supports(translation) | ||
] | ||
self.helper = FormHelper(self) | ||
|
@@ -687,12 +687,12 @@ | |
self.helper.form_tag = False | ||
|
||
def get_field_doc(self, field: forms.Field) -> tuple[str, str] | None: | ||
return ("user/files", f"upload-{field.name}") | ||
|
||
def remove_translation_choice(self, value) -> None: | ||
"""Remove given file upload method from choices.""" | ||
choices = self.fields["method"].choices | ||
self.fields["method"].choices = [ | ||
choice for choice in choices if choice[0] != value | ||
] | ||
|
||
|
@@ -732,11 +732,11 @@ | |
form = ExtraUploadForm | ||
kwargs["initial"] = {"author_name": user.full_name, "author_email": user.email} | ||
elif user.has_perm("upload.overwrite", translation): | ||
form = UploadForm | ||
else: | ||
form = SimpleUploadForm | ||
result = form(*args, **kwargs) | ||
for method in [x[0] for x in result.fields["method"].choices]: | ||
if not check_upload_method_permissions(user, translation, method): | ||
result.remove_translation_choice(method) | ||
# Remove approved choice for non review projects | ||
|
@@ -804,50 +804,50 @@ | |
self.cleaned_data["offset"] = 1 | ||
return self.cleaned_data["offset"] | ||
|
||
def items(self): | ||
items = [] | ||
# Skip checksum and offset as these change | ||
ignored = {"offset", "checksum"} | ||
for param in sorted(self.cleaned_data): | ||
value = self.cleaned_data[param] | ||
# We don't care about empty values or ignored ones | ||
if value is None or param in ignored: | ||
continue | ||
if isinstance(value, bool): | ||
# Only store true values | ||
if value: | ||
items.append((param, "1")) | ||
elif isinstance(value, int): | ||
# Avoid storing 0 values | ||
if value > 0: | ||
items.append((param, str(value))) | ||
elif isinstance(value, datetime): | ||
# Convert date to string | ||
items.append((param, value.date().isoformat())) | ||
elif isinstance(value, list): | ||
items.extend((param, val) for val in value) | ||
elif isinstance(value, User): | ||
items.append((param, value.username)) | ||
elif value: | ||
# It should be a string here | ||
items.append((param, value)) | ||
return items | ||
|
||
def urlencode(self): | ||
return urlencode(self.items()) | ||
|
||
def reset_offset(self): | ||
""" | ||
Reset form offset. | ||
|
||
This is needed to avoid issues when using the form as the default for | ||
any new search. | ||
""" | ||
data = copy.copy(self.data) # pylint: disable=access-member-before-definition | ||
data["offset"] = "1" | ||
data["checksum"] = "" | ||
self.data = data | ||
return self | ||
# def items(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the code is no longer used, just remove it. |
||
# items = [] | ||
# # Skip checksum and offset as these change | ||
# ignored = {"offset", "checksum"} | ||
# for param in sorted(self.cleaned_data): | ||
# value = self.cleaned_data[param] | ||
# # We don't care about empty values or ignored ones | ||
# if value is None or param in ignored: | ||
# continue | ||
# if isinstance(value, bool): | ||
# # Only store true values | ||
# if value: | ||
# items.append((param, "1")) | ||
# elif isinstance(value, int): | ||
# # Avoid storing 0 values | ||
# if value > 0: | ||
# items.append((param, str(value))) | ||
# elif isinstance(value, datetime): | ||
# # Convert date to string | ||
# items.append((param, value.date().isoformat())) | ||
# elif isinstance(value, list): | ||
# items.extend((param, val) for val in value) | ||
# elif isinstance(value, User): | ||
# items.append((param, value.username)) | ||
# elif value: | ||
# # It should be a string here | ||
# items.append((param, value)) | ||
# return items | ||
|
||
# def urlencode(self): | ||
# return urlencode(self.items()) | ||
|
||
# def reset_offset(self): | ||
# """ | ||
# Reset form offset. | ||
|
||
# This is needed to avoid issues when using the form as the default for | ||
# any new search. | ||
# """ | ||
# data = copy.copy(self.data) # pylint: disable=access-member-before-definition | ||
# data["offset"] = "1" | ||
# data["checksum"] = "" | ||
# self.data = data | ||
# return self | ||
|
||
|
||
class PositionSearchForm(SearchForm): | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please bring back the original markup?