Skip to content

Commit a6e54c4

Browse files
committed
Merge remote-tracking branch 'upstream/unstable' into remove-vuetify-5597
2 parents 6853201 + f80529f commit a6e54c4

55 files changed

Lines changed: 4978 additions & 1715 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/call-pull-request-target.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: Handle pull request events
22
on:
33
pull_request_target:
4-
types: [review_requested, labeled]
4+
types: [opened, review_requested, labeled]
55
jobs:
66
call-workflow:
77
name: Call shared workflow

.github/workflows/deploytest.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
steps:
3030
- uses: actions/checkout@v6
3131
- name: Use pnpm
32-
uses: pnpm/action-setup@v5
32+
uses: pnpm/action-setup@v6.0.3
3333
- name: Use Node.js
3434
uses: actions/setup-node@v6
3535
with:
@@ -59,7 +59,7 @@ jobs:
5959
# Use uv to install dependencies directly from requirements files
6060
uv pip sync requirements.txt
6161
- name: Use pnpm
62-
uses: pnpm/action-setup@v5
62+
uses: pnpm/action-setup@v6.0.3
6363
- name: Use Node.js
6464
uses: actions/setup-node@v6
6565
with:

.github/workflows/frontendtest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
steps:
3030
- uses: actions/checkout@v6
3131
- name: Use pnpm
32-
uses: pnpm/action-setup@v5
32+
uses: pnpm/action-setup@v6.0.3
3333
- name: Use Node.js
3434
uses: actions/setup-node@v6
3535
with:

.github/workflows/i18n-download.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
run: uv pip sync requirements.txt
2323

2424
- name: Use pnpm
25-
uses: pnpm/action-setup@v5
25+
uses: pnpm/action-setup@v6.0.3
2626

2727
- name: Use Node.js
2828
uses: actions/setup-node@v6

.github/workflows/i18n-upload.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
run: uv pip sync requirements.txt
2323

2424
- name: Use pnpm
25-
uses: pnpm/action-setup@v5
25+
uses: pnpm/action-setup@v6.0.3
2626

2727
- name: Use Node.js
2828
uses: actions/setup-node@v6

.github/workflows/pre-commit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
python-version: '3.10'
3939
ignore-nothing-to-cache: 'true'
4040
- name: Use pnpm
41-
uses: pnpm/action-setup@v5
41+
uses: pnpm/action-setup@v6.0.3
4242
- name: Use Node.js
4343
uses: actions/setup-node@v6
4444
with:

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ repos:
77
exclude: '^.+?\.ttf$'
88
- id: debug-statements
99
- id: end-of-file-fixer
10-
exclude: '^.+?\.json.+?\.yml$'
10+
exclude: '^.+?(\.json|\.po)$'
1111
- repo: https://github.com/PyCQA/flake8
1212
rev: 7.1.2
1313
hooks:

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ migrate:
3939
# 4) Remove the management command from this `deploy-migrate` recipe
4040
# 5) Repeat!
4141
deploy-migrate:
42-
echo "Nothing to do here!"
42+
python contentcuration/manage.py ensure_versioned_databases_exist & python contentcuration/manage.py create_channel_versions & wait
4343

4444
contentnodegc:
4545
python contentcuration/manage.py garbage_collect

contentcuration/contentcuration/db/models/manager.py

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from django.db.utils import OperationalError
1010
from django_cte import CTEQuerySet
1111
from le_utils.constants import content_kinds
12+
from le_utils.constants import modalities
1213
from mptt.managers import TreeManager
1314
from mptt.signals import node_moved
1415

@@ -359,6 +360,15 @@ def _recurse_to_create_tree(
359360
)
360361
)
361362
source_copy_id_map[source.id] = copy["id"]
363+
364+
if self._is_unit_topic(source.kind_id, copy.get("extra_fields")):
365+
copy["extra_fields"] = {
366+
**copy["extra_fields"],
367+
"options": self._remap_unit_options(
368+
copy["extra_fields"]["options"], source_copy_id_map
369+
),
370+
}
371+
362372
return copy
363373

364374
def _all_nodes_to_copy(self, node, excluded_descendants):
@@ -394,7 +404,7 @@ def copy_node(
394404
if progress_tracker:
395405
progress_tracker.set_total(total_nodes)
396406

397-
return self._copy(
407+
nodes, _ = self._copy(
398408
node,
399409
target,
400410
position,
@@ -406,6 +416,7 @@ def copy_node(
406416
batch_size,
407417
progress_tracker=progress_tracker,
408418
)
419+
return nodes
409420

410421
def _copy(
411422
self,
@@ -424,7 +435,7 @@ def _copy(
424435
:type progress_tracker: contentcuration.utils.celery.ProgressTracker|None
425436
"""
426437
if node.rght - node.lft < batch_size:
427-
copied_nodes = self._deep_copy(
438+
copied_nodes, node_map = self._deep_copy(
428439
node,
429440
target,
430441
position,
@@ -436,7 +447,7 @@ def _copy(
436447
)
437448
if progress_tracker:
438449
progress_tracker.increment(len(copied_nodes))
439-
return copied_nodes
450+
return copied_nodes, node_map
440451
node_copy = self._shallow_copy(
441452
node,
442453
target,
@@ -451,8 +462,9 @@ def _copy(
451462
children = node.get_children().order_by("lft")
452463
if excluded_descendants:
453464
children = children.exclude(node_id__in=excluded_descendants.keys())
465+
combined_map = {node.id: node_copy.id}
454466
for child in children:
455-
self._copy(
467+
_, child_map = self._copy(
456468
child,
457469
node_copy,
458470
"last-child",
@@ -464,7 +476,19 @@ def _copy(
464476
batch_size,
465477
progress_tracker=progress_tracker,
466478
)
467-
return [node_copy]
479+
combined_map.update(child_map)
480+
481+
if self._is_unit_topic(node.kind_id, node.extra_fields):
482+
remapped_extra_fields = {
483+
**node_copy.extra_fields,
484+
"options": self._remap_unit_options(
485+
node.extra_fields["options"], combined_map
486+
),
487+
}
488+
self.filter(pk=node_copy.pk).update(extra_fields=remapped_extra_fields)
489+
node_copy.extra_fields = remapped_extra_fields
490+
491+
return [node_copy], combined_map
468492

469493
def _copy_tags(self, source_copy_id_map):
470494
from contentcuration.models import ContentTag
@@ -582,6 +606,27 @@ def _copy_associated_objects(self, source_copy_id_map):
582606

583607
self._copy_tags(source_copy_id_map)
584608

609+
@staticmethod
610+
def _is_unit_topic(kind_id, extra_fields):
611+
return (
612+
kind_id == content_kinds.TOPIC
613+
and isinstance(extra_fields, dict)
614+
and extra_fields.get("options", {}).get("modality") == modalities.UNIT
615+
)
616+
617+
@staticmethod
618+
def _remap_unit_options(options, source_copy_id_map):
619+
remapped = dict(options)
620+
621+
if "lesson_objectives" in remapped:
622+
remapped["lesson_objectives"] = {
623+
source_copy_id_map[old_id]: objectives
624+
for old_id, objectives in remapped["lesson_objectives"].items()
625+
if old_id in source_copy_id_map
626+
}
627+
628+
return remapped
629+
585630
def _shallow_copy(
586631
self,
587632
node,
@@ -665,4 +710,4 @@ def _deep_copy(
665710

666711
self._copy_associated_objects(source_copy_id_map)
667712

668-
return new_nodes
713+
return new_nodes, source_copy_id_map
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<template>
2+
3+
<KTextbox
4+
:value="value"
5+
type="email"
6+
:label="label || $tr('emailLabel')"
7+
:maxlength="maxlength"
8+
:disabled="disabled"
9+
:invalid="hasError"
10+
:invalidText="errorText"
11+
:showInvalidText="hasError"
12+
v-bind="$attrs"
13+
@input="handleInput"
14+
@blur="$emit('blur')"
15+
/>
16+
17+
</template>
18+
19+
20+
<script>
21+
22+
export default {
23+
name: 'StudioEmailField',
24+
props: {
25+
value: {
26+
type: String,
27+
default: '',
28+
},
29+
label: {
30+
type: String,
31+
default: null,
32+
},
33+
disabled: {
34+
type: Boolean,
35+
default: false,
36+
},
37+
errorMessages: {
38+
type: Array,
39+
default: () => [],
40+
},
41+
maxlength: {
42+
type: [String, Number],
43+
default: null,
44+
},
45+
},
46+
computed: {
47+
hasError() {
48+
return this.errorMessages && this.errorMessages.length > 0;
49+
},
50+
errorText() {
51+
return this.hasError ? this.errorMessages[0] : '';
52+
},
53+
},
54+
methods: {
55+
handleInput(value) {
56+
this.$emit('input', value.trim());
57+
},
58+
},
59+
$trs: {
60+
emailLabel: 'Email address',
61+
},
62+
};
63+
64+
</script>

0 commit comments

Comments
 (0)