Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
21d1a86
Include permalink and sanitized name in the response when updating a …
brianhogg Feb 15, 2026
765fc81
Make sure settings panel updates.
brianhogg Feb 15, 2026
3589a5b
Default to published when creating a new quiz.
brianhogg Feb 15, 2026
2a0d49b
Show permalink when creating a new quiz and saving, or editing (if it…
brianhogg Feb 15, 2026
c3f2361
Listen to the name change to update the text input correctly.
brianhogg Feb 16, 2026
a2bc5b4
Listen to the name change to update the text input correctly when add…
brianhogg Feb 16, 2026
e942a32
Add post title from title data to generate a permalink, if not overri…
brianhogg Feb 16, 2026
1d3f5ee
WIP: Adding experimental description field to lessons.
brianhogg Feb 16, 2026
3ce4ef6
Moving to lesson model instead of hidden detail in schema.
brianhogg Feb 16, 2026
3b61b91
Switch to allowing edit only if the content is blank, or if the conte…
brianhogg Feb 17, 2026
a53ff2b
Change the lesson data rather than saving the flag. Otherwise content…
brianhogg Feb 17, 2026
02f7470
Close the editor sidebar if the lesson we're currently editing is bei…
brianhogg Feb 17, 2026
54eebf1
Attempt to fix tests.
brianhogg Feb 17, 2026
00e5986
WIP: Trying to hide add existing lesson modal after picking a lesson.
brianhogg Feb 17, 2026
c947ef2
Destroy the webui-popover elements. Fixes #3097
brianhogg Feb 19, 2026
df8649e
Selecting the first section on load. Improved highlighting of the sel…
brianhogg Feb 19, 2026
c00b606
Fix for cloned lessons showing content editor incorrectly.
brianhogg Feb 19, 2026
7cc1e6a
Remove console logs.
brianhogg Feb 19, 2026
6729084
Avoiding propagation up to the top-level of quiz when the select is c…
brianhogg Feb 19, 2026
83b8219
Listen for changes to assignment model.
brianhogg Feb 20, 2026
66026e8
Changelogs
brianhogg Feb 20, 2026
6576b2d
Changelogs
brianhogg Feb 20, 2026
46b9a57
Spacing
brianhogg Feb 20, 2026
26678da
Fixing double pubsub call.
brianhogg Feb 20, 2026
3e7d46e
Reverting spacing.
brianhogg Feb 20, 2026
1809a9b
Merge branch 'dev' into course-builder-improvements
brianhogg Apr 7, 2026
d490100
Fix DOM accumulation with add existing lesson popup.
brianhogg Apr 9, 2026
c947d1e
Listen to name change for quizzes too.
brianhogg Apr 9, 2026
3b02691
Merge branch 'dev' into course-builder-improvements
brianhogg Apr 9, 2026
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
4 changes: 4 additions & 0 deletions .changelogs/course-builder-improvements-1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
significance: minor
type: added
entry: Lesson content can be edited within the Course Builder for new lessons,
or existing lessons with no existing content.
3 changes: 3 additions & 0 deletions .changelogs/course-builder-improvements-2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
significance: patch
type: fixed
entry: Close lesson settings panel when lesson has been trashed.
9 changes: 9 additions & 0 deletions .changelogs/course-builder-improvements.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
significance: minor
type: changed
links:
- "#3033"
- "#3056"
- "#3097"
- "#2938"
- "#3030"
entry: Various course builder fixes, with quizzes set to published by default.
26 changes: 26 additions & 0 deletions assets/js/builder/Controllers/Sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,18 @@ define( [], function() {
model.set( 'id', info.id );
delete model._unsavedChanges.id;
}

if ( info.permalink ) {
model.set( 'permalink', info.permalink );
}
if ( info.name ) {
model.set( 'name', info.name );
}

if ( info.content_added_in_builder ) {
model.set( 'content_added_in_builder', info.content_added_in_builder );
}

maybe_restart_tracking( model, info );

// check children
Expand Down Expand Up @@ -460,6 +472,20 @@ define( [], function() {
model.set( 'id', info.id );
delete model._unsavedChanges.id;
}

// Update permalink and name if provided by the server.
if ( info.permalink ) {
model.set( 'permalink', info.permalink );
}
if ( info.name ) {
model.set( 'name', info.name );
}

if ( info.content_added_in_builder ) {
model.set( 'content_added_in_builder', info.content_added_in_builder );
}


maybe_restart_tracking( model, info );

// check children
Expand Down
2 changes: 2 additions & 0 deletions assets/js/builder/Models/Lesson.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ define( [ 'Models/Quiz', 'Models/_Relationships', 'Models/_Utilities', 'Schemas/
quiz: {}, // Quiz model/data.
quiz_enabled: 'no',

content_added_in_builder: '',

_forceSync: false,

};
Expand Down
2 changes: 1 addition & 1 deletion assets/js/builder/Models/Quiz.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ define( [
type: 'llms_quiz',
lesson_id: '',

status: 'draft',
status: 'publish',

// editable fields.
content: '',
Expand Down
37 changes: 28 additions & 9 deletions assets/js/builder/Schemas/Lesson.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,34 @@ define( [], function() {
title: LLMS.l10n.translate( 'General Settings' ),
toggleable: true,
fields: [
[
{
attribute: 'permalink',
id: 'permalink',
type: 'permalink',
},
], [
{
attribute: 'video_embed',
[
{
attribute: 'permalink',
id: 'permalink',
type: 'permalink',
},
], [
{
attribute: 'content',
id: 'content',
label: LLMS.l10n.translate( 'Content' ),
type: 'editor',
condition: function() {
return '' === this.get( 'content' ) || 'yes' === this.get( 'content_added_in_builder' );
},
},
], [
{
id: 'content-page-builder-notice',
label: LLMS.l10n.translate( 'Content' ),
type: 'page_builder_notice',
condition: function() {
return '' !== this.get( 'content' ) && 'yes' !== this.get( 'content_added_in_builder' );
},
},
], [
{
attribute: 'video_embed',
id: 'video-embed',
label: LLMS.l10n.translate( 'Video Embed URL' ),
type: 'video_embed',
Expand Down
21 changes: 21 additions & 0 deletions assets/js/builder/Views/Assignment.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ define( [
*/
this.model.set_parent( this.lesson );

this.listenTo( this.model, 'change:permalink', this.render_settings );

}

this.on( 'model-trashed', this.on_trashed );
Expand Down Expand Up @@ -154,6 +156,23 @@ define( [

},

/**
* Re-render the settings subview when permalink updates after saving.
*
* @since [version]
*
* @return {Void}
*/
render_settings: function() {

var view = this.get_subview( 'settings' );
if ( view && view.instance ) {
view.instance.render();
this.init_selects();
}

},

/**
* Adds a new assignment to a lesson which currently has no assignment associated with it.
*
Expand All @@ -176,6 +195,7 @@ define( [
this.lesson.set( 'assignment_enabled', 'yes' );
this.lesson.set( 'assignment', this.model );

this.listenTo( this.model, 'change:permalink', this.render_settings );
this.render();

} else {
Expand Down Expand Up @@ -221,6 +241,7 @@ define( [
this.lesson.set( 'assignment', assignment );
this.model = assignment;

this.listenTo( this.model, 'change:permalink', this.render_settings );
this.render();

},
Expand Down
9 changes: 7 additions & 2 deletions assets/js/builder/Views/Course.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ define( [

Backbone.pubSub.on( 'lesson-selected', this.active_lesson_change, this );

// Select the first section by default on load.
var firstSection = this.model.get( 'sections' ).first();
if ( firstSection ) {
this.sectionListView.setSelectedModel( firstSection );
}

},

/**
Expand Down Expand Up @@ -167,8 +173,7 @@ define( [
*/
on_section_toggle: function( model ) {

var selected = model.get( '_expanded' ) ? [ model ] : [];
this.sectionListView.setSelectedModels( selected );
this.sectionListView.setSelectedModel( model );

},

Expand Down
19 changes: 15 additions & 4 deletions assets/js/builder/Views/Elements.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ define( [ 'Models/Section', 'Views/Section', 'Models/Lesson', 'Views/Lesson', 'V

event.preventDefault();

var pop = new Popover( {
var pop, onLessonSelect;

pop = new Popover( {
el: '#llms-existing-lesson',
args: {
backdrop: true,
Expand All @@ -144,13 +146,22 @@ define( [ 'Models/Section', 'Views/Section', 'Models/Lesson', 'Views/Lesson', 'V
post_type: 'lesson',
searching_message: LLMS.l10n.translate( 'Search for existing lessons...' ),
} ).render().$el,
onHide: function() {
Backbone.pubSub.off( 'lesson-search-select', onLessonSelect );
},
Comment thread
brianhogg marked this conversation as resolved.
}
} );

onLessonSelect = function() {
pop.hide();

// Ref #3097 — pop.hide() doesn't always remove the DOM elements.
$( '.webui-popover' ).remove();
$( '.webui-popover-backdrop' ).remove();
};

pop.show();
Backbone.pubSub.on( 'lesson-search-select', function() {
pop.hide()
} );
Backbone.pubSub.once( 'lesson-search-select', onLessonSelect );

},

Expand Down
3 changes: 3 additions & 0 deletions assets/js/builder/Views/LessonEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ define( [
var change_events = window.llms.hooks.applyFilters( 'llms_lesson_rerender_change_events', [
'change:date_available',
'change:drip_method',
'change:permalink',
'change:content_added_in_builder',
'change:name',
'change:time_available',
] );
_.each( change_events, function( event ) {
Expand Down
29 changes: 29 additions & 0 deletions assets/js/builder/Views/Quiz.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ define( [
this.model.set_parent( this.lesson );

this.listenTo( this.model, 'change:_points', this.render_points );
this.listenTo( this.model, 'change:permalink', this.render_settings );
this.listenTo( this.model, 'change:name', this.render_settings );

}

Expand Down Expand Up @@ -226,6 +228,27 @@ define( [

},

/**
* Re-render the settings subview.
*
* Used when the permalink is updated after saving so the settings
* panel reflects the new permalink without a full re-render.
*
* @since [version]
*
* @return {Void}
*/
render_settings: function() {

var view = this.get_subview( 'settings' );
if ( view && view.instance ) {
view.instance.render();
this.init_datepickers();
this.init_selects();
}

},

/**
* Bulk expand / collapse question buttons.
*
Expand Down Expand Up @@ -261,6 +284,9 @@ define( [
}

this.model = quiz;
this.listenTo( this.model, 'change:_points', this.render_points );
this.listenTo( this.model, 'change:permalink', this.render_settings );
this.listenTo( this.model, 'change:name', this.render_settings );
this.render();

},
Expand Down Expand Up @@ -298,6 +324,9 @@ define( [

this.lesson.add_quiz( quiz );
this.model = this.lesson.get( 'quiz' );
this.listenTo( this.model, 'change:_points', this.render_points );
this.listenTo( this.model, 'change:permalink', this.render_settings );
Comment thread
brianhogg marked this conversation as resolved.
this.listenTo( this.model, 'change:name', this.render_settings );
this.render();

},
Expand Down
1 change: 0 additions & 1 deletion assets/js/builder/Views/Section.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ define( [
*/
events: _.defaults( {

'click': 'select',
'click .expand': 'expand',
'click .collapse': 'collapse',
'click .shift-up--section': 'shift_up',
Expand Down
2 changes: 1 addition & 1 deletion assets/js/builder/Views/SectionList.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ define( [ 'Views/Section', 'Views/_Receivable' ], function( SectionView, Receiva
el: '#llms-sections',

events : {
'mousedown > li.llms-section > .llms-builder-header .llms-headline' : '_listItem_onMousedown',
'mousedown > li.llms-section' : '_listItem_onMousedown',
// 'dblclick > li, tbody > tr > td' : '_listItem_onDoubleClick',
'click' : '_listBackground_onClick',
'click ul.collection-view' : '_listBackground_onClick',
Expand Down
2 changes: 2 additions & 0 deletions assets/js/builder/Views/_Editable.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ define( [], function() {
*/
on_select: function( event ) {

event.stopPropagation();

var $el = $( event.target ),
multi = ( $el.attr( 'multiple' ) ),
attr = $el.attr( 'name' ),
Expand Down
5 changes: 5 additions & 0 deletions assets/js/builder/Views/_Trashable.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ define( [], function() {
// publish event
Backbone.pubSub.trigger( 'model-trashed', this.model );

// close the editor sidebar if the trashed model is the one currently being edited
if ( this.model.get( '_selected' ) ) {
Backbone.pubSub.trigger( 'sidebar-editor-close' );
}

// trigger local event so extending views can run other actions where necessary
this.trigger( 'model-trashed', this.model );

Expand Down
3 changes: 3 additions & 0 deletions assets/scss/admin/_course-builder.scss
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ body.admin_page_llms-course-builder {
.llms-lessons { overflow: visible; }
}
&.selected {
border-left: 3px solid $color-brand-blue;
box-shadow: 2px 2px 8px rgba( 0, 0, 0, 0.12 );
margin-left: -2px;
.llms-drag-utility.drag-section {
border-color: $color-brand-blue;
}
Expand Down
27 changes: 26 additions & 1 deletion includes/admin/class.llms.admin.builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,17 @@ private static function update_lessons( $lessons, $section ) {

$skip_props = apply_filters( 'llms_builder_update_lesson_skip_props', array( 'quiz' ) );

// Don't overwrite content if the content editor doesn't display.
if ( ! $created && '' !== $lesson->get( 'content' ) && ! llms_parse_bool( $lesson->get( 'content_added_in_builder' ) ) ) {
$skip_props[] = 'content';
}

if ( '' === $lesson->get( 'content' ) && isset( $lesson_data['content'] ) && '' !== $lesson_data['content']
&& ! isset( $lesson_data['content_added_in_builder'] ) ) {
// We're adding content via the builder for the first time; add a flag saying so.
$lesson_data['content_added_in_builder'] = 'yes';
}

// Update all updatable properties.
foreach ( $properties as $prop ) {
if ( isset( $lesson_data[ $prop ] ) && ! in_array( $prop, $skip_props, true ) ) {
Expand All @@ -1097,6 +1108,11 @@ private static function update_lessons( $lessons, $section ) {
$lesson->set( 'name', sanitize_title( $lesson_data['title'] ) );
}

// Include permalink, slug, and editor type in the response so the builder can update the model.
$res['permalink'] = get_permalink( $lesson->get( 'id' ) );
$res['name'] = $lesson->get( 'name' );
$res['content_added_in_builder'] = $lesson->get( 'content_added_in_builder' );

// Remove revision prevention.
remove_filter( 'wp_revisions_to_keep', '__return_zero', 999 );

Expand Down Expand Up @@ -1253,7 +1269,12 @@ private static function update_quiz( $quiz_data, $lesson ) {
// Create a quiz.
if ( self::is_temp_id( $quiz_data['id'] ) ) {

$quiz = new LLMS_Quiz( 'new' );
$quiz = new LLMS_Quiz(
'new',
array(
'post_title' => isset( $quiz_data['title'] ) ? $quiz_data['title'] : __( 'New Quiz', 'lifterlms' ),
)
);

// Update existing quiz.
} else {
Expand Down Expand Up @@ -1301,6 +1322,10 @@ private static function update_quiz( $quiz_data, $lesson ) {
}
}

// Include permalink and slug in the response so the builder can update the model.
$res['permalink'] = get_permalink( $quiz->get( 'id' ) );
$res['name'] = $quiz->get( 'name' );

if ( isset( $quiz_data['questions'] ) && is_array( $quiz_data['questions'] ) ) {
$res['questions'] = self::update_questions( $quiz_data['questions'], $quiz );
}
Expand Down
Loading
Loading