Index: lams_central/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -rd3313eb898d654f090e6ea6c99b3232a65f759f2 -ref32c5d5a859467fe2a98b31251041d4e0c0582c --- lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision d3313eb898d654f090e6ea6c99b3232a65f759f2) +++ lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision ef32c5d5a859467fe2a98b31251041d4e0c0582c) @@ -592,6 +592,7 @@ authoring.fla.page.prop.hours = hours authoring.fla.page.prop.minutes = minutes authoring.fla.page.prop.gate.activity.finish.based = Since learner finished previous activity? +authoring.fla.page.prop.gate.stop.at.preceding = Stop learners at preceding activity? authoring.fla.page.prop.conditions.create = Create conditions authoring.fla.page.prop.gate.conditions.map = Map gate conditions authoring.fla.page.prop.branching.type = Branching type: Index: lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/LdTemplateController.java =================================================================== diff -u -r0162b2cbc7bcaac107007efe67db525f2abeb91a -ref32c5d5a859467fe2a98b31251041d4e0c0582c --- lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/LdTemplateController.java (.../LdTemplateController.java) (revision 0162b2cbc7bcaac107007efe67db525f2abeb91a) +++ lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/LdTemplateController.java (.../LdTemplateController.java) (revision ef32c5d5a859467fe2a98b31251041d4e0c0582c) @@ -403,7 +403,7 @@ /* ************************************** Non-Tool Activity methods ******************************************** */ protected ObjectNode createGateActivity(AtomicInteger uiid, int order, Integer[] layoutCoords, String activityTitle, - String activityDescription) { + String activityDescription, boolean gateStopAtPrecedingActivity) { ObjectNode activityJSON = JsonNodeFactory.instance.objectNode(); Integer[] pos = layoutCoords; @@ -425,14 +425,16 @@ } activityJSON.put(AuthoringJsonTags.ACTIVITY_TYPE_ID, Activity.PERMISSION_GATE_ACTIVITY_TYPE); activityJSON.put(AuthoringJsonTags.GATE_ACTIVITY_LEVEL_ID, GateActivity.LEARNER_GATE_LEVEL); + activityJSON.put(AuthoringJsonTags.GATE_STOP_AT_PRECEDING_ACTIVITY, gateStopAtPrecedingActivity); return activityJSON; } protected ObjectNode createScheduledGateActivity(AtomicInteger uiid, int order, Integer[] layoutCoords, - String activityTitle, String activityDescription, Long startOffset) { + String activityTitle, String activityDescription, Long startOffset, boolean gateStopAtPrecedingActivity) { - ObjectNode activityJSON = createGateActivity(uiid, order, layoutCoords, activityTitle, activityDescription); + ObjectNode activityJSON = createGateActivity(uiid, order, layoutCoords, activityTitle, activityDescription, + gateStopAtPrecedingActivity); activityJSON.put(AuthoringJsonTags.ACTIVITY_TYPE_ID, Activity.SCHEDULE_GATE_ACTIVITY_TYPE); activityJSON.put(AuthoringJsonTags.GATE_START_OFFSET, startOffset); Index: lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/TBLTemplateController.java =================================================================== diff -u -r0162b2cbc7bcaac107007efe67db525f2abeb91a -ref32c5d5a859467fe2a98b31251041d4e0c0582c --- lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/TBLTemplateController.java (.../TBLTemplateController.java) (revision 0162b2cbc7bcaac107007efe67db525f2abeb91a) +++ lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/TBLTemplateController.java (.../TBLTemplateController.java) (revision ef32c5d5a859467fe2a98b31251041d4e0c0582c) @@ -150,10 +150,10 @@ activityTitle = data.getText("boilerplate.before.ira.gate"); if (data.useScheduledGates && data.iraStartOffset != null) { activities.add(createScheduledGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), - activityTitle, null, data.iraStartOffset)); + activityTitle, null, data.iraStartOffset, true)); } else { activities.add(createGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), - activityTitle, activityTitle)); + activityTitle, activityTitle, true)); } // iRA Test - Assessment @@ -182,10 +182,10 @@ activityTitle = data.getText("boilerplate.before.tra.gate"); if (data.useScheduledGates && data.traStartOffset != null) { activities.add(createScheduledGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), - activityTitle, null, data.traStartOffset)); + activityTitle, null, data.traStartOffset, true)); } else { activities.add(createGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), - activityTitle, activityTitle)); + activityTitle, activityTitle, true)); } // tRA Test @@ -218,11 +218,12 @@ String gateTitleBeforeAppEx = data.getText("boilerplate.before.app.ex", new String[] { applicationExercise.title }); if (data.useScheduledGates && data.aeStartOffset != null) { - activities.add(createScheduledGateActivity(maxUIID, order++, - calcGateOffset(currentActivityPosition), gateTitleBeforeAppEx, null, data.aeStartOffset)); + activities + .add(createScheduledGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), + gateTitleBeforeAppEx, null, data.aeStartOffset, true)); } else { activities.add(createGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), - gateTitleBeforeAppEx, gateTitleBeforeAppEx)); + gateTitleBeforeAppEx, gateTitleBeforeAppEx, true)); } // Application Exercise @@ -263,7 +264,7 @@ String gateTitle = data.getText("boilerplate.before.app.ex.noticeboard", new String[] { noticeboardCountAsString }); activities.add(createGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), - gateTitle, gateTitle)); + gateTitle, gateTitle, true)); } currentActivityPosition = calcPositionNextRight(currentActivityPosition); String notebookTitle = data.getText("boilerplate.grouped.ae.noticeboard.num", @@ -293,7 +294,7 @@ // Stop! String gateTitle = data.getText("boilerplate.before.peer.review"); activities.add(createGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), gateTitle, - gateTitle)); + gateTitle, true)); currentActivityPosition = calcPositionNextRight(currentActivityPosition); String peerReviewTitle = data.getText("boilerplate.peerreview"); @@ -307,7 +308,8 @@ if (data.useReflection) { // Stop! - activities.add(createGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), null, null)); + activities.add( + createGateActivity(maxUIID, order++, calcGateOffset(currentActivityPosition), null, null, true)); // Individual Reflection currentActivityPosition = calcPositionNextRight(currentActivityPosition); Index: lams_central/web/authoring/authoring.jsp =================================================================== diff -u -re49f4ca2772f41c3e5dce498bc2d32a66b4f31ad -ref32c5d5a859467fe2a98b31251041d4e0c0582c --- lams_central/web/authoring/authoring.jsp (.../authoring.jsp) (revision e49f4ca2772f41c3e5dce498bc2d32a66b4f31ad) +++ lams_central/web/authoring/authoring.jsp (.../authoring.jsp) (revision ef32c5d5a859467fe2a98b31251041d4e0c0582c) @@ -754,6 +754,10 @@
+ + + + @@ -783,15 +787,15 @@ - + - + @@ -808,28 +812,36 @@ - + - + + + + + - + - + Index: lams_central/web/includes/javascript/authoring/authoringActivity.js =================================================================== diff -u -r471a9703a083f8a36f111ec7be0a18d285942afb -ref32c5d5a859467fe2a98b31251041d4e0c0582c --- lams_central/web/includes/javascript/authoring/authoringActivity.js (.../authoringActivity.js) (revision 471a9703a083f8a36f111ec7be0a18d285942afb) +++ lams_central/web/includes/javascript/authoring/authoringActivity.js (.../authoringActivity.js) (revision ef32c5d5a859467fe2a98b31251041d4e0c0582c) @@ -141,13 +141,16 @@ /** * Constructor for a Gate Activity. */ - GateActivity : function(id, uiid, x, y, title, description, readOnly, gateType, startTimeOffset, gateActivityCompletionBased, password) { + GateActivity : function(id, uiid, x, y, title, description, readOnly, gateType, startTimeOffset, + gateActivityCompletionBased, gateStopAtPrecedingActivity, password) { this.id = +id || null; this.uiid = +uiid || ++layout.ld.maxUIID; this.title = title; this.description = description; this.readOnly = readOnly; this.gateType = gateType || 'permission'; + this.gateStopAtPrecedingActivity = gateStopAtPrecedingActivity; + if (gateType == 'schedule') { var day = 24*60; this.offsetDay = Math.floor(startTimeOffset/day); @@ -160,6 +163,7 @@ if (gateType == 'password') { this.password = password; } + // mapping between tool output and gate states ("branches"), if applicable this.conditionsToBranches = []; this.transitions = { Index: lams_central/web/includes/javascript/authoring/authoringGeneral.js =================================================================== diff -u -r445e72a02a97730a82c5db8c690b2618c378d412 -ref32c5d5a859467fe2a98b31251041d4e0c0582c --- lams_central/web/includes/javascript/authoring/authoringGeneral.js (.../authoringGeneral.js) (revision 445e72a02a97730a82c5db8c690b2618c378d412) +++ lams_central/web/includes/javascript/authoring/authoringGeneral.js (.../authoringGeneral.js) (revision ef32c5d5a859467fe2a98b31251041d4e0c0582c) @@ -796,7 +796,6 @@ // activities in the another LD have different clousures, so they can not be imported directly // they need to be recreated from a scratch with current LD being their context var frameWindow = $('#ldStoreDialogImportPartFrame', layout.ldStoreDialog)[0].contentWindow, - frameActivities = frameWindow.layout.activities, frameActivityDefs = frameWindow.ActivityDefs, // the local activity addActivity = null; @@ -825,7 +824,8 @@ } else if (activity instanceof frameActivityDefs.GateActivity) { addActivity = new ActivityDefs.GateActivity( null, activity.uiid, 0, 0, activity.title, activity.description, false, activity.gateType, - activity.startTimeoffset, activity.gateActivityCompletionBased + activity.startTimeoffset, activity.gateActivityCompletionBased, activity.gateStopAtPrecedingActivity, + activity.password ); } else if (activity instanceof frameActivityDefs.GroupingActivity) { addActivity = new ActivityDefs.GroupingActivity( @@ -1925,6 +1925,7 @@ gateType, activityData.gateStartTimeOffset, activityData.gateActivityCompletionBased, + activityData.gateStopAtPrecedingActivity, activityData.gatePassword); if (gateType == 'system'){ @@ -2570,6 +2571,7 @@ iconPath = null, isGrouped = activity.grouping ? true : false, gateActivityCompletionBased = false, + gateStopAtPrecedingActivity = false, activityTransitions = activity instanceof ActivityDefs.BranchingActivity ? activity.end.transitions : activity.transitions; @@ -2619,21 +2621,26 @@ }); } else if (activity instanceof ActivityDefs.GateActivity){ + let previousActivityExists = activityTransitions && activityTransitions.to && activityTransitions.to.length > 0; + switch(activity.gateType) { case 'sync' : activityTypeID = 3; break; case 'schedule' : activityTypeID = 4; - gateActivityCompletionBased = activity.gateActivityCompletionBased - //check the previous activity is available as well - && (activityTransitions && activityTransitions.to && activityTransitions.to.length > 0); + gateActivityCompletionBased = activity.gateActivityCompletionBased && previousActivityExists; + gateStopAtPrecedingActivity = activity.gateStopAtPrecedingActivity && previousActivityExists; break; - case 'permission' : activityTypeID = 5; break; + case 'permission' : + activityTypeID = 5; + gateStopAtPrecedingActivity = activity.gateStopAtPrecedingActivity && previousActivityExists; + break; case 'password' : activityTypeID = 16; break; case 'system' : activityTypeID = 9; systemGate = activity; break; case 'condition' : activityTypeID = 14; - + gateStopAtPrecedingActivity = activity.gateStopAtPrecedingActivity && previousActivityExists; + if (activity.input) { $.each(activity.conditionsToBranches, function(index){ if (!this.branch) { @@ -2760,6 +2767,7 @@ 'gateStartTimeOffset' : activity.gateType == 'schedule' ? activity.offsetDay*24*60 + activity.offsetHour*60 + activity.offsetMinute : null, 'gateActivityCompletionBased' : gateActivityCompletionBased, + 'gateStopAtPrecedingActivity' : gateStopAtPrecedingActivity, 'gatePassword' : activity.gateType == 'password' ? activity.password : null, 'gateActivityLevelID' : activity instanceof ActivityDefs.GateActivity ? 1 : null, 'minOptions' : activity.minOptions || null, Index: lams_central/web/includes/javascript/authoring/authoringProperty.js =================================================================== diff -u -r56793ebe8b7fa9e4eb2d961b13a9f2b8984fb389 -ref32c5d5a859467fe2a98b31251041d4e0c0582c --- lams_central/web/includes/javascript/authoring/authoringProperty.js (.../authoringProperty.js) (revision 56793ebe8b7fa9e4eb2d961b13a9f2b8984fb389) +++ lams_central/web/includes/javascript/authoring/authoringProperty.js (.../authoringProperty.js) (revision ef32c5d5a859467fe2a98b31251041d4e0c0582c) @@ -215,37 +215,57 @@ activity.gateType = $('.propertiesContentFieldGateType', content).val(); + $('.propertiesContentRowGateTypeBased', content).hide(); if (activity.gateType == 'schedule') { // show inputs for setting delay before the gate is closed $(".propertiesContentRowGateSchedule", content).show(); activity.offsetDay = +$('.propertiesContentFieldOffsetDay', content).val(); activity.offsetHour = +$('.propertiesContentFieldOffsetHour', content).val(); activity.offsetMinute = +$('.propertiesContentFieldOffsetMinute', content).val(); + + // both of these options must not be on at the same time + // stop-at-preceding-activity may prevent preceding activity from completion, + // meaning that timer-from-previous-activity-completion will never start activity.gateActivityCompletionBased = $('.propertiesContentFieldActivityCompletionBased', content).is(':checked'); - } else { - $(".propertiesContentRowGateSchedule", content).hide(); + if (activity.gateActivityCompletionBased) { + activity.gateStopAtPrecedingActivity = false; + $('.propertiesContentFieldStopAtPrecedingActivity', content).prop('disabled', true).prop('checked', false); + } else { + activity.gateStopAtPrecedingActivity = $('.propertiesContentFieldStopAtPrecedingActivity', content).is(':checked'); + $('.propertiesContentFieldStopAtPrecedingActivity', content).prop('disabled', false); + } + + if (activity.gateStopAtPrecedingActivity) { + activity.gateActivityCompletionBased = false; + $('.propertiesContentFieldActivityCompletionBased', content).prop('disabled', true).prop('checked', false); + } else { + $('.propertiesContentFieldActivityCompletionBased', content).prop('disabled', false); + } } if (activity.gateType == 'password') { $(".propertiesContentRowGatePassword", content).show(); activity.password = $('.propertiesContentFieldPassword', content).val(); - } else { - $(".propertiesContentRowGatePassword", content).hide(); } // Gate can be input-based - var inputRow = $('.propertiesContentFieldInput', content).closest('tr'), - inputDefinitionRows = $('.propertiesContentRowConditions', content); if (activity.gateType == 'condition') { + var inputRow = $('.propertiesContentFieldInput', content).closest('tr'), + inputDefinitionRows = $('.propertiesContentRowConditions', content); + + activity.gateStopAtPrecedingActivity = $('.propertiesContentFieldStopAtPrecedingActivity', content).is(':checked'); + activity.input = inputRow.show().find('option:selected').data('input'); if (activity.input) { inputDefinitionRows.show(); } else { - inputDefinitionRows.hide(); + $('.propertiesContentFieldStopAtPrecedingActivity', content).closest('tr').show(); } - } else { - inputRow.hide(); - inputDefinitionRows.hide(); + } + + if (activity.gateType == 'permission') { + $(".propertiesContentRowPermission", content).show(); + activity.gateStopAtPrecedingActivity = $('.propertiesContentFieldStopAtPrecedingActivity', content).is(':checked'); } if (redrawNeeded) { @@ -277,8 +297,11 @@ .on('input', changeFunction); $('.propertiesContentFieldActivityCompletionBased', content) - .attr('checked', activity.gateActivityCompletionBased? 'checked' : null); + .attr('checked', activity.gateActivityCompletionBased ? 'checked' : null); + $('.propertiesContentFieldStopAtPrecedingActivity', content) + .attr('checked', activity.gateStopAtPrecedingActivity ? 'checked' : null); + $('.propertiesContentFieldPassword', content) .val(activity.password); Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20210713.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20210713.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20210713.sql (revision ef32c5d5a859467fe2a98b31251041d4e0c0582c) @@ -0,0 +1,18 @@ +-- Turn off autocommit, so nothing is committed if there is an error +SET AUTOCOMMIT = 0; +SET FOREIGN_KEY_CHECKS=0; +-- Put all sql statements below here + +--LDEV-5200 Remove learning library groups feature +DROP TABLE IF EXISTS lams_learning_library_group; + +-- Update server version so authoring auto rearrange can kick in + +UPDATE lams_configuration SET config_value = '4.5' WHERE config_key = 'ServerVersionNumber'; + +-- Put all sql statements above here + +-- If there were no errors, commit and restore autocommit to on +COMMIT; +SET AUTOCOMMIT = 1; +SET FOREIGN_KEY_CHECKS=1; Fisheye: Tag ef32c5d5a859467fe2a98b31251041d4e0c0582c refers to a dead (removed) revision in file `lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20210709.sql'. Fisheye: No comparison available. Pass `N' to diff?
+ + + +