Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
class="answer-number"
type="number"
:rules="[numericRule]"
@change="updateAnswerText($event, answerIdx)"
/>
<VTextField v-else :value="answer.answer" class="no-border" type="number" />
</div>
Expand Down Expand Up @@ -388,10 +389,6 @@
}
},
updateAnswerText(newAnswerText, answerIdx) {
if (newAnswerText === this.answers[answerIdx].answer) {
return;
}

const updatedAnswers = [...this.answers];
updatedAnswers[answerIdx].answer = newAnswerText;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,33 @@ import { isNodeComplete } from 'shared/utils/validation';
import db from 'shared/data/db';
import { TABLE_NAMES } from 'shared/data/constants';

function updateNodeComplete(nodeId, context) {
const node = context.rootGetters['contentNode/getContentNode'](nodeId);
const complete = isNodeComplete({
nodeDetails: node,
assessmentItems: context.getters.getAssessmentItems(nodeId),
files: context.rootGetters['file/getContentNodeFiles'](nodeId),
});
return context.dispatch(
'contentNode/updateContentNode',
{ id: nodeId, complete },
{ root: true }
);
// We implement a retry mechanism to ensure that we wait for retrival of contentnode
// when all the nodes for the
// currently displayed topic in the tree view are reloaded
function updateNodeComplete(nodeId, context, maxTries = 10, delayMs = 100) {
let tries = 0;

function tryUpdate() {
const node = context.rootGetters['contentNode/getContentNode'](nodeId);
if (node) {
const complete = isNodeComplete({
nodeDetails: node,
assessmentItems: context.getters.getAssessmentItems(nodeId),
files: context.rootGetters['file/getContentNodeFiles'](nodeId),
});
return context.dispatch(
'contentNode/updateContentNode',
{ id: nodeId, complete },
{ root: true }
);
} else if (tries < maxTries) {
tries++;
setTimeout(tryUpdate, delayMs);
} else {
console.error(`updateNodeComplete: Node ${nodeId} not found in Vuex after ${maxTries} tries`);
}
}
tryUpdate();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Generated by Django 3.2.24 on 2025-04-17 15:16
from django.db import migrations
from django.db import models


class Migration(migrations.Migration):

dependencies = [
("contentcuration", "0150_bloompub_format_and_preset"),
]

operations = [
migrations.AlterField(
model_name="fileformat",
name="extension",
field=models.CharField(
choices=[
("mp4", "MP4 Video"),
("webm", "WEBM Video"),
("vtt", "VTT Subtitle"),
("mp3", "MP3 Audio"),
("pdf", "PDF Document"),
("jpg", "JPG Image"),
("jpeg", "JPEG Image"),
("png", "PNG Image"),
("gif", "GIF Image"),
("json", "JSON"),
("svg", "SVG Image"),
("perseus", "Perseus Exercise"),
("graphie", "Graphie Exercise"),
("zip", "HTML5 Zip"),
("h5p", "H5P"),
("zim", "ZIM"),
("epub", "ePub Document"),
("bloompub", "Bloom Document"),
("bloomd", "Bloom Document"),
("kpub", "Kolibri HTML5 Article"),
],
max_length=40,
primary_key=True,
serialize=False,
),
),
migrations.AlterField(
model_name="formatpreset",
name="id",
field=models.CharField(
choices=[
("high_res_video", "High Resolution"),
("low_res_video", "Low Resolution"),
("video_thumbnail", "Thumbnail"),
("video_subtitle", "Subtitle"),
("video_dependency", "Video (dependency)"),
("audio", "Audio"),
("audio_thumbnail", "Thumbnail"),
("audio_dependency", "audio (dependency)"),
("document", "Document"),
("epub", "ePub Document"),
("document_thumbnail", "Thumbnail"),
("exercise", "Exercise"),
("exercise_thumbnail", "Thumbnail"),
("exercise_image", "Exercise Image"),
("exercise_graphie", "Exercise Graphie"),
("channel_thumbnail", "Channel Thumbnail"),
("topic_thumbnail", "Thumbnail"),
("html5_zip", "HTML5 Zip"),
("html5_dependency", "HTML5 Dependency (Zip format)"),
("html5_thumbnail", "HTML5 Thumbnail"),
("h5p", "H5P Zip"),
("h5p_thumbnail", "H5P Thumbnail"),
("zim", "Zim"),
("zim_thumbnail", "Zim Thumbnail"),
("qti", "QTI Zip"),
("qti_thumbnail", "QTI Thumbnail"),
("slideshow_image", "Slideshow Image"),
("slideshow_thumbnail", "Slideshow Thumbnail"),
("slideshow_manifest", "Slideshow Manifest"),
("imscp_zip", "IMSCP Zip"),
("bloompub", "Bloom Document"),
("kpub", "Kolibri HTML5 Article"),
],
max_length=150,
primary_key=True,
serialize=False,
),
),
]
5 changes: 5 additions & 0 deletions contentcuration/contentcuration/viewsets/contentnode.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,11 @@ def decode_cursor(self, request):
if value is None:
return None

try:
value = int(value)
except ValueError:
raise ValidationError("lft must be an integer but an invalid value was given.")

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

def encode_cursor(self, cursor):
Expand Down
115 changes: 115 additions & 0 deletions contentcuration/kolibri_content/migrations/0023_auto_20250417_1516.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Generated by Django 3.2.24 on 2025-04-17 15:16
from django.db import migrations
from django.db import models


class Migration(migrations.Migration):

dependencies = [
("content", "0022_auto_20240915_1414"),
]

operations = [
migrations.AlterField(
model_name="file",
name="extension",
field=models.CharField(
blank=True,
choices=[
("mp4", "MP4 Video"),
("webm", "WEBM Video"),
("vtt", "VTT Subtitle"),
("mp3", "MP3 Audio"),
("pdf", "PDF Document"),
("jpg", "JPG Image"),
("jpeg", "JPEG Image"),
("png", "PNG Image"),
("gif", "GIF Image"),
("json", "JSON"),
("svg", "SVG Image"),
("perseus", "Perseus Exercise"),
("graphie", "Graphie Exercise"),
("zip", "HTML5 Zip"),
("h5p", "H5P"),
("zim", "ZIM"),
("epub", "ePub Document"),
("bloompub", "Bloom Document"),
("bloomd", "Bloom Document"),
("kpub", "Kolibri HTML5 Article"),
],
max_length=40,
),
),
migrations.AlterField(
model_name="file",
name="preset",
field=models.CharField(
blank=True,
choices=[
("high_res_video", "High Resolution"),
("low_res_video", "Low Resolution"),
("video_thumbnail", "Thumbnail"),
("video_subtitle", "Subtitle"),
("video_dependency", "Video (dependency)"),
("audio", "Audio"),
("audio_thumbnail", "Thumbnail"),
("audio_dependency", "audio (dependency)"),
("document", "Document"),
("epub", "ePub Document"),
("document_thumbnail", "Thumbnail"),
("exercise", "Exercise"),
("exercise_thumbnail", "Thumbnail"),
("exercise_image", "Exercise Image"),
("exercise_graphie", "Exercise Graphie"),
("channel_thumbnail", "Channel Thumbnail"),
("topic_thumbnail", "Thumbnail"),
("html5_zip", "HTML5 Zip"),
("html5_dependency", "HTML5 Dependency (Zip format)"),
("html5_thumbnail", "HTML5 Thumbnail"),
("h5p", "H5P Zip"),
("h5p_thumbnail", "H5P Thumbnail"),
("zim", "Zim"),
("zim_thumbnail", "Zim Thumbnail"),
("qti", "QTI Zip"),
("qti_thumbnail", "QTI Thumbnail"),
("slideshow_image", "Slideshow Image"),
("slideshow_thumbnail", "Slideshow Thumbnail"),
("slideshow_manifest", "Slideshow Manifest"),
("imscp_zip", "IMSCP Zip"),
("bloompub", "Bloom Document"),
("kpub", "Kolibri HTML5 Article"),
],
max_length=150,
),
),
migrations.AlterField(
model_name="localfile",
name="extension",
field=models.CharField(
blank=True,
choices=[
("mp4", "MP4 Video"),
("webm", "WEBM Video"),
("vtt", "VTT Subtitle"),
("mp3", "MP3 Audio"),
("pdf", "PDF Document"),
("jpg", "JPG Image"),
("jpeg", "JPEG Image"),
("png", "PNG Image"),
("gif", "GIF Image"),
("json", "JSON"),
("svg", "SVG Image"),
("perseus", "Perseus Exercise"),
("graphie", "Graphie Exercise"),
("zip", "HTML5 Zip"),
("h5p", "H5P"),
("zim", "ZIM"),
("epub", "ePub Document"),
("bloompub", "Bloom Document"),
("bloomd", "Bloom Document"),
("kpub", "Kolibri HTML5 Article"),
],
max_length=40,
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Generated by Django 3.2.24 on 2025-04-17 15:16
from django.db import migrations
from django.db import models


class Migration(migrations.Migration):

dependencies = [
("kolibri_public", "0005_alter_localfile_extension"),
]

operations = [
migrations.AlterField(
model_name="file",
name="preset",
field=models.CharField(
blank=True,
choices=[
("high_res_video", "High Resolution"),
("low_res_video", "Low Resolution"),
("video_thumbnail", "Thumbnail"),
("video_subtitle", "Subtitle"),
("video_dependency", "Video (dependency)"),
("audio", "Audio"),
("audio_thumbnail", "Thumbnail"),
("audio_dependency", "audio (dependency)"),
("document", "Document"),
("epub", "ePub Document"),
("document_thumbnail", "Thumbnail"),
("exercise", "Exercise"),
("exercise_thumbnail", "Thumbnail"),
("exercise_image", "Exercise Image"),
("exercise_graphie", "Exercise Graphie"),
("channel_thumbnail", "Channel Thumbnail"),
("topic_thumbnail", "Thumbnail"),
("html5_zip", "HTML5 Zip"),
("html5_dependency", "HTML5 Dependency (Zip format)"),
("html5_thumbnail", "HTML5 Thumbnail"),
("h5p", "H5P Zip"),
("h5p_thumbnail", "H5P Thumbnail"),
("zim", "Zim"),
("zim_thumbnail", "Zim Thumbnail"),
("qti", "QTI Zip"),
("qti_thumbnail", "QTI Thumbnail"),
("slideshow_image", "Slideshow Image"),
("slideshow_thumbnail", "Slideshow Thumbnail"),
("slideshow_manifest", "Slideshow Manifest"),
("imscp_zip", "IMSCP Zip"),
("bloompub", "Bloom Document"),
("kpub", "Kolibri HTML5 Article"),
],
max_length=150,
),
),
migrations.AlterField(
model_name="localfile",
name="extension",
field=models.CharField(
blank=True,
choices=[
("mp4", "MP4 Video"),
("webm", "WEBM Video"),
("vtt", "VTT Subtitle"),
("mp3", "MP3 Audio"),
("pdf", "PDF Document"),
("jpg", "JPG Image"),
("jpeg", "JPEG Image"),
("png", "PNG Image"),
("gif", "GIF Image"),
("json", "JSON"),
("svg", "SVG Image"),
("perseus", "Perseus Exercise"),
("graphie", "Graphie Exercise"),
("zip", "HTML5 Zip"),
("h5p", "H5P"),
("zim", "ZIM"),
("epub", "ePub Document"),
("bloompub", "Bloom Document"),
("bloomd", "Bloom Document"),
("kpub", "Kolibri HTML5 Article"),
],
max_length=40,
),
),
]
2 changes: 1 addition & 1 deletion requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ djangorestframework==3.15.1
psycopg2-binary==2.9.5
django-js-reverse==0.9.1
django-registration==3.4
le-utils==0.2.5
le-utils==0.2.10
gunicorn==20.1.0
django-postmark==0.1.6
jsonfield==3.1.0
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ jsonschema==4.17.3
# via -r requirements.in
kombu==5.2.4
# via celery
le-utils==0.2.7
le-utils==0.2.10
# via -r requirements.in
packaging==24.0
# via
Expand Down