feat: reorder chapters, lessons
This commit is contained in:
@@ -16,17 +16,27 @@
|
||||
{% macro Header() %}
|
||||
<header class="sticky">
|
||||
<div class="container form-width">
|
||||
<button class="btn btn-primary btn-sm btn-save-course pull-right mt-1">
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
|
||||
{% if course.name %}
|
||||
<a class="btn btn-default btn-sm pull-right mt-1 mr-2" href="/courses/{{ course.name }}">
|
||||
{{ _("Preview") }}
|
||||
</a>
|
||||
{% endif %}
|
||||
<div class="edit-header">
|
||||
<div class="page-title"> {{ _("Course Details") }} </div>
|
||||
|
||||
<div class="align-self-center">
|
||||
{% if course.name %}
|
||||
<a class="btn btn-default btn-sm mr-2" href="/courses/{{ course.name }}">
|
||||
{{ _("Preview") }}
|
||||
</a>
|
||||
|
||||
<a class="btn btn-default btn-sm mr-2" href="/courses/{{ course.name }}/outline">
|
||||
{{ _("Course Outline") }}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<button class="btn btn-primary btn-sm btn-save-course">
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-title"> {{ _("Course Details") }} </div>
|
||||
</div>
|
||||
</header>
|
||||
{% endmacro %}
|
||||
|
||||
@@ -75,7 +75,7 @@ const save_course = (e) => {
|
||||
indicator: "green",
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.href = `/courses/${data.message}/outline`;
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -23,15 +23,26 @@
|
||||
{% macro Header() %}
|
||||
<header class="sticky">
|
||||
<div class="container form-width">
|
||||
<button class="btn btn-primary btn-sm pull-right mt-1 btn-add-chapter">
|
||||
<span>
|
||||
{{ _("Add Chapter") }}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div class="page-title">
|
||||
{{ course.title if course.name else _("Course Outline") }}
|
||||
<div class="edit-header">
|
||||
<div>
|
||||
<div class="page-title">
|
||||
{{ course.title if course.name else _("Course Outline") }}
|
||||
</div>
|
||||
<div class="vertically-center small">
|
||||
<a class="dark-links" href="/courses/{{ course.name }}/edit">{{ _("Course Details") }}</a>
|
||||
<img class="icon icon-sm mr-0" src="/assets/lms/icons/chevron-right.svg">
|
||||
<span class="breadcrumb-destination">{{ _("Course Outline") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary btn-sm btn-add-chapter align-self-center">
|
||||
<span>
|
||||
{{ _("Add Chapter") }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</header>
|
||||
{% endmacro %}
|
||||
@@ -39,15 +50,17 @@
|
||||
|
||||
{% macro Outline(chapters) %}
|
||||
{% if chapters %}
|
||||
{% for chapter in chapters %}
|
||||
{% set chapter_index = loop.index %}
|
||||
{% set lessons = get_lessons(course.name, chapter) %}
|
||||
<article>
|
||||
<div class="chapter-dropzone">
|
||||
{% for chapter in chapters %}
|
||||
{% set chapter_index = loop.index %}
|
||||
{% set lessons = get_lessons(course.name, chapter) %}
|
||||
<div class="common-card-style column-card chapter-container p-4 my-5" data-chapter="{{ chapter.name }}" data-idx="{{ loop.index }}">
|
||||
<div class="level">
|
||||
<svg class="icon icon-xs level-item mr-2">
|
||||
<use class="" href="#icon-drag"></use>
|
||||
</svg>
|
||||
<div class="drag-handle">
|
||||
<svg class="icon icon-xs level-item mr-2">
|
||||
<use class="" href="#icon-drag"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="bold-heading chapters-title">
|
||||
{{ chapter.title }}
|
||||
</div>
|
||||
@@ -59,21 +72,25 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% for lesson in lessons %}
|
||||
<div class="outline-lesson level">
|
||||
<svg class="icon icon-xs level-item mr-2">
|
||||
<use class="" href="#icon-drag"></use>
|
||||
</svg>
|
||||
<!-- <div class="icon-bg">
|
||||
<svg class="icon icon-sm level-item">
|
||||
<use class="" href="#{{ lesson.icon }}">
|
||||
{% if lessons | length %}
|
||||
<div class="lesson-dropzone">
|
||||
{% for lesson in lessons %}
|
||||
<div class="outline-lesson level" data-lesson="{{ lesson.name }}">
|
||||
<div class="drag-handle">
|
||||
<svg class="icon icon-xs level-item mr-2">
|
||||
<use class="" href="#icon-drag"></use>
|
||||
</svg>
|
||||
</div> -->
|
||||
<a class="clickable" href="/courses/{{ course.name }}/learn/{{ chapter_index }}.{{ loop.index }}/edit">
|
||||
{{ lesson.title }}
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a class="clickable" href="/courses/{{ course.name }}/learn/{{ chapter_index }}.{{ loop.index }}/edit">
|
||||
{{ lesson.title }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div class="align-self-start mt-4">
|
||||
<a class="btn btn-secondary btn-sm" href="/courses/{{ course.name }}/learn/{{ loop.index }}.{{ lessons | length + 1 }}/edit">
|
||||
@@ -88,8 +105,8 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endmacro %}
|
||||
@@ -141,7 +158,6 @@
|
||||
</article>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary btn-sm mr-2" data-dismiss="modal" aria-label="Close">
|
||||
{{ _("Discard") }}
|
||||
@@ -168,9 +184,6 @@
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button class="btn btn-default btn-sm btn-add-chapter">
|
||||
<!-- <svg class="icon icon-xs">
|
||||
<use class="" href="#icon-add"></use>
|
||||
</svg> -->
|
||||
<span>
|
||||
{{ _("Add Chapter") }}
|
||||
</span>
|
||||
|
||||
@@ -10,6 +10,14 @@ frappe.ready(() => {
|
||||
$("#save-chapter").click((e) => {
|
||||
save_chapter(e);
|
||||
});
|
||||
|
||||
$(".lesson-dropzone").each((i, el) => {
|
||||
setSortable(el);
|
||||
});
|
||||
|
||||
$(".chapter-dropzone").each((i, el) => {
|
||||
setSortable(el);
|
||||
});
|
||||
});
|
||||
|
||||
const show_chapter_modal = (e) => {
|
||||
@@ -49,3 +57,73 @@ const save_chapter = (e) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const setSortable = (el) => {
|
||||
new Sortable(el, {
|
||||
group: "drag",
|
||||
handle: ".drag-handle",
|
||||
animation: 150,
|
||||
fallbackOnBody: true,
|
||||
swapThreshold: 0.65,
|
||||
onEnd: (e) => {
|
||||
if ($(e.item).hasClass("outline-lesson")) reorder_lesson(e);
|
||||
else reorder_chapter(e);
|
||||
},
|
||||
onMove: (e) => {
|
||||
if (
|
||||
$(e.dragged).hasClass("outline-lesson") &&
|
||||
$(e.to).hasClass("chapter-dropzone")
|
||||
)
|
||||
return false;
|
||||
if (
|
||||
$(e.dragged).hasClass("chapter-edit") &&
|
||||
$(e.to).hasClass("lesson-dropzone")
|
||||
)
|
||||
return false;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const reorder_lesson = (e) => {
|
||||
let old_chapter = $(e.from).closest(".chapter-container").data("chapter");
|
||||
let new_chapter = $(e.to).closest(".chapter-container").data("chapter");
|
||||
|
||||
if (old_chapter == new_chapter && e.oldIndex == e.newIndex) return;
|
||||
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_course.lms_course.reorder_lesson",
|
||||
args: {
|
||||
old_chapter: old_chapter,
|
||||
old_lesson_array: $(e.from)
|
||||
.children()
|
||||
.map((i, e) => $(e).data("lesson"))
|
||||
.get(),
|
||||
new_chapter: new_chapter,
|
||||
new_lesson_array: $(e.to)
|
||||
.children()
|
||||
.map((i, e) => $(e).data("lesson"))
|
||||
.get(),
|
||||
},
|
||||
callback: (data) => {
|
||||
window.location.reload();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const reorder_chapter = (e) => {
|
||||
if (e.oldIndex == e.newIndex) return;
|
||||
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_course.lms_course.reorder_chapter",
|
||||
args: {
|
||||
new_index: e.newIndex + 1,
|
||||
chapter_array: $(e.to)
|
||||
.children()
|
||||
.map((i, e) => $(e).data("chapter"))
|
||||
.get(),
|
||||
},
|
||||
callback: (data) => {
|
||||
window.location.reload();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user