Skip to content

Commit be139fb

Browse files
authored
Merge pull request #5293 from learningequality/hotfixes
Merge down Hotfixes
2 parents 417c7a1 + 3230fd7 commit be139fb

5 files changed

Lines changed: 63 additions & 40 deletions

File tree

contentcuration/contentcuration/frontend/channelEdit/views/trash/TrashModal.vue

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@
253253
];
254254
},
255255
items() {
256-
return sortBy(this.getContentNodeChildren(this.trashId), 'modified');
256+
return sortBy(this.getContentNodeChildren(this.trashId), 'modified').reverse();
257257
},
258258
backLink() {
259259
return {
@@ -277,9 +277,9 @@
277277
},
278278
},
279279
created() {
280-
(this.loadContentNodes({ parent__in: [this.rootId] }),
281-
this.loadAncestors({ id: this.nodeId }),
282-
this.loadNodes());
280+
this.loadContentNodes({ parent__in: [this.rootId] });
281+
this.loadAncestors({ id: this.nodeId });
282+
this.loadNodes();
283283
},
284284
mounted() {
285285
this.updateTabTitle(this.$store.getters.appendChannelName(this.$tr('trashModalTitle')));
@@ -298,10 +298,12 @@
298298
this.loading = false;
299299
return;
300300
}
301-
this.loadChildren({ parent: this.trashId }).then(childrenResponse => {
302-
this.loading = false;
303-
this.more = childrenResponse.more || null;
304-
});
301+
this.loadChildren({ parent: this.trashId, ordering: '-modified' }).then(
302+
childrenResponse => {
303+
this.loading = false;
304+
this.more = childrenResponse.more || null;
305+
},
306+
);
305307
},
306308
moveNodes(target) {
307309
return this.moveContentNodes({

contentcuration/contentcuration/frontend/channelEdit/vuex/contentNode/actions.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,11 @@ export function loadContentNodeByNodeId(context, nodeId) {
7171
});
7272
}
7373

74-
export function loadChildren(context, { parent, published = null, complete = null }) {
75-
const params = { parent, max_results: 25 };
74+
export function loadChildren(
75+
context,
76+
{ parent, published = null, complete = null, ordering = null },
77+
) {
78+
const params = { parent, max_results: 25, ordering };
7679
if (published !== null) {
7780
params.published = published;
7881
}

contentcuration/contentcuration/frontend/shared/data/resources.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,14 @@ class IndexedDBResource {
557557
collection = collection.filter(filterFn);
558558
}
559559
if (paginationActive) {
560+
// Default pagination field is 'lft'
561+
let paginationField = 'lft';
562+
if (params.ordering) {
563+
paginationField = params.ordering.replace(/^-/, '');
564+
}
565+
// Determine the operator based on the ordering direction.
566+
const operator = params.ordering && params.ordering.startsWith('-') ? 'lt' : 'gt';
567+
560568
let results;
561569
if (sortBy) {
562570
// If we still have a sortBy value here, then we have not sorted using orderBy
@@ -574,7 +582,8 @@ class IndexedDBResource {
574582
more: hasMore
575583
? {
576584
...params,
577-
lft__gt: results[maxResults - 1].lft,
585+
// Dynamically set the pagination cursor based on the pagination field and operator.
586+
[`${paginationField}__${operator}`]: results[maxResults - 1][paginationField],
578587
}
579588
: null,
580589
};

contentcuration/contentcuration/viewsets/contentnode.py

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ def update(self, instance, validated_data):
518518

519519

520520
def retrieve_thumbail_src(item):
521-
""" Get either the encoding or the url to use as the <img> src attribute """
521+
"""Get either the encoding or the url to use as the <img> src attribute"""
522522
try:
523523
if item.get("thumbnail_encoding"):
524524
encoding = json.loads(item.get("thumbnail_encoding"))
@@ -705,54 +705,64 @@ def dict_if_none(obj, field_name=None):
705705

706706
class ContentNodePagination(ValuesViewsetCursorPagination):
707707
"""
708-
A simplified cursor pagination class for ContentNodeViewSet.
709-
Instead of using an opaque cursor, it uses the lft value for filtering.
710-
As such, if this pagination scheme is used without applying a filter
711-
that will guarantee membership to a specific MPTT tree, such as parent
712-
or tree_id, the pagination scheme will not be predictable.
708+
A simplified cursor pagination class
709+
Instead of using a fixed 'lft' cursor, it dynamically sets the pagination field and operator
710+
based on the incoming `ordering` query parameter.
713711
"""
714712

715-
cursor_query_param = "lft__gt"
716-
ordering = "lft"
717713
page_size_query_param = "max_results"
718714
max_page_size = 100
719715

716+
def get_pagination_params(self):
717+
# Default ordering is "lft" if not provided.
718+
ordering_param = self.request.query_params.get("ordering", "lft")
719+
# Remove the leading '-' if present to get the field name.
720+
pagination_field = ordering_param.lstrip("-")
721+
# Determine operator: if ordering starts with '-', use __lt; otherwise __gt.
722+
operator = "__lt" if ordering_param.startswith("-") else "__gt"
723+
return pagination_field, operator
724+
720725
def decode_cursor(self, request):
721726
"""
722-
Given a request with a cursor, return a `Cursor` instance.
727+
Given a request with a cursor parameter, return a `Cursor` instance.
728+
The cursor parameter name is dynamically built from the pagination field and operator.
723729
"""
724-
# Determine if we have a cursor, and if so then decode it.
725-
value = request.query_params.get(self.cursor_query_param)
730+
pagination_field, operator = self.get_pagination_params()
731+
cursor_param = f"{pagination_field}{operator}"
732+
value = request.query_params.get(cursor_param)
726733
if value is None:
727734
return None
728735

729-
try:
730-
value = int(value)
731-
except ValueError:
732-
raise ValidationError(
733-
"lft must be an integer but an invalid value was given."
734-
)
736+
if pagination_field == "lft":
737+
try:
738+
value = int(value)
739+
except ValueError:
740+
raise ValidationError(
741+
"lft must be an integer but an invalid value was given."
742+
)
735743

736744
return Cursor(offset=0, reverse=False, position=value)
737745

738746
def encode_cursor(self, cursor):
739747
"""
740-
Given a Cursor instance, return an url with query parameter.
748+
Given a Cursor instance, return a URL with the dynamic pagination cursor query parameter.
741749
"""
742-
return replace_query_param(
743-
self.base_url, self.cursor_query_param, str(cursor.position)
744-
)
750+
pagination_field, operator = self.get_pagination_params()
751+
cursor_param = f"{pagination_field}{operator}"
752+
return replace_query_param(self.base_url, cursor_param, str(cursor.position))
745753

746754
def get_more(self):
755+
"""
756+
Construct a "more" URL (or query parameters) that includes the pagination cursor
757+
built from the dynamic field and operator.
758+
"""
759+
pagination_field, operator = self.get_pagination_params()
760+
cursor_param = f"{pagination_field}{operator}"
747761
position, offset = self._get_more_position_offset()
748762
if position is None and offset is None:
749763
return None
750764
params = self.request.query_params.copy()
751-
params.update(
752-
{
753-
self.cursor_query_param: position,
754-
}
755-
)
765+
params.update({cursor_param: position})
756766
return params
757767

758768

@@ -1068,7 +1078,7 @@ def copy(
10681078
position=None,
10691079
mods=None,
10701080
excluded_descendants=None,
1071-
**kwargs
1081+
**kwargs,
10721082
):
10731083
target, position = self.validate_targeting_args(target, position)
10741084

@@ -1133,7 +1143,7 @@ def perform_create(self, serializer, change=None):
11331143
)
11341144

11351145
def update_descendants(self, pk, mods):
1136-
""" Update a node and all of its descendants with the given mods """
1146+
"""Update a node and all of its descendants with the given mods"""
11371147
root = ContentNode.objects.get(id=pk)
11381148

11391149
if root.kind_id != content_kinds.TOPIC:

deploy/includes/content/_proxy.conf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ limit_except GET HEAD OPTIONS {
77

88
proxy_http_version 1.1;
99
proxy_set_header Host $proxy_host;
10-
proxy_set_header Accept-Encoding Identity;
1110
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
1211
proxy_redirect off;
1312
proxy_buffering off;

0 commit comments

Comments
 (0)