Skip to content

Commit

Permalink
Merge pull request #2611 from oat-sa/feature/AUT-1389/edit-min-max-logic
Browse files Browse the repository at this point in the history
chore: new logic for minMax component: min value can be 0
  • Loading branch information
taopkorczak authored Dec 11, 2024
2 parents 266eb7c + 0e2ff23 commit ea41300
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 63 deletions.
2 changes: 1 addition & 1 deletion views/css/item-creator.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion views/css/item-creator.css.map

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions views/cypress/utils/set-response.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,6 @@ export function addResponseProcessing(
//set correct response
cy.get('[name="defineCorrect"]').click({force: true});
//able to set min/max
cy.getSettled('[class="panel min-max-panel"]')
.find('[name="lowerBound-toggler"]')
.click({force:true})
.should('not.have.value', '0');
cy.getSettled('[class="panel min-max-panel"]')
.find('[name="lowerBound-toggler"]')
.click({force:true});
Expand Down
2 changes: 1 addition & 1 deletion views/js/loader/qtiLoader.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion views/js/loader/taoQtiItem.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion views/js/loader/taoQtiItem.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion views/js/loader/taoQtiItemRunner.es5.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion views/js/loader/taoQtiItemRunner.es5.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion views/js/loader/taoQtiItemRunner.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion views/js/loader/taoQtiItemRunner.min.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions views/js/qtiCreator/model/mixin/editableInteraction.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ define([

//se the default value for the score default value
response.mappingAttributes.defaultValue = 0;
response.mappingAttributes.lowerBound = 0;

//set renderer
renderer = this.getRenderer();
Expand Down
136 changes: 93 additions & 43 deletions views/js/qtiCreator/widgets/component/minMax/minMax.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ define([
//default help message
helpMessage: __(
'The minimum number of choices that the candidate is required to select to form a valid response.'
)
),

// determines if field can be null
canBeNull: false,
},
max: {
//name of the max field
Expand All @@ -62,7 +65,10 @@ define([
//default help message
helpMessage: __(
'The maximum number of choices that the candidate is required to select to form a valid response.'
)
),

// determines if field can be null
canBeNull: false,
},

//Minimum threshold for both
Expand All @@ -75,7 +81,7 @@ define([
syncValues: true,

//does the input can have decimal value
allowDecimal: false
allowDecimal: true
};

/**
Expand Down Expand Up @@ -146,11 +152,12 @@ define([
const config = this.getConfig();

if (isFieldSupported(field)) {
if (this.is('rendered')) {
return _.parseInt(controls[field].input.val());
if (!this.is('rendered')) {
return config[field].value;
}

return config[field].value;
const inputValue = controls[field].input.val();
return inputValue === '' ? null : this.parseNumber(inputValue);
}
},

Expand All @@ -170,6 +177,26 @@ define([
return this.getValue(fields.max);
},

/**
* Get the lower threshold for a field
* @param {String} field - min or max
* @returns {Number} the lower threshold value
*/
getLowerThreshold: function(field) {
const config = this.getConfig();
return config[field].lowerThreshold ? config[field].lowerThreshold : config.lowerThreshold;
},

/**
* Get the upper threshold for a field
* @param {String} field - min or max
* @returns {Number} the upper threshold value
*/
getUpperThreshold: function(field) {
const config = this.getConfig();
return config[field].upperThreshold ? config[field].upperThreshold : config.upperThreshold;
},

/**
* Set the value of a given field
* @param {String} field - min or max
Expand All @@ -178,23 +205,26 @@ define([
* @throws {TypeError} if the field is unknown
*/
setValue: function setValue(field, value) {
if (!isFieldSupported(field)) {
return this;
}

const config = this.getConfig();
const intValue = _.parseInt(value);
const lowerThreshold = config[field].lowerThreshold
? config[field].lowerThreshold
: config.lowerThreshold;
const upperThreshold = config[field].upperThreshold
? config[field].upperThreshold
: config.upperThreshold;
const intValue = this.parseNumber(value);
const lowerThreshold = this.getLowerThreshold(field);
const upperThreshold = this.getUpperThreshold(field);

if (
isFieldSupported(field) &&
_.isNumber(intValue) &&
intValue >= lowerThreshold &&
intValue <= upperThreshold
) {
if (config[field].canBeNull && value === null) {
if (this.is('rendered')) {
controls[field].input.val('').trigger('change');
}
config[field].value = null;
return this;
}

if (_.isNumber(intValue) && (intValue >= lowerThreshold) && intValue <= upperThreshold) {
if (this.is('rendered') && controls[field].input.val() !== `${intValue}`) {
return controls[field].input.val(intValue).trigger('change');
controls[field].input.val(intValue).trigger('change');
}

config[field].value = intValue;
Expand Down Expand Up @@ -233,8 +263,8 @@ define([
const config = this.getConfig();
if (_.isNumber(lower) && _.isNumber(upper) && upper >= lower) {
if (!field) {
config.lowerThreshold = _.parseInt(lower);
config.upperThreshold = _.parseInt(upper);
config.lowerThreshold = this.parseNumber(lower);
config.upperThreshold = this.parseNumber(upper);

if (this.is('rendered')) {
const fieldOptions = {
Expand All @@ -252,8 +282,8 @@ define([
}
}
} else if (field === 'min' || field === 'max') {
config[field].lowerThreshold = _.parseInt(lower);
config[field].upperThreshold = _.parseInt(upper);
config[field].lowerThreshold = this.parseNumber(lower);
config[field].upperThreshold = this.parseNumber(upper);

if (this.is('rendered')) {
const fieldOptions = {
Expand Down Expand Up @@ -286,7 +316,7 @@ define([
return true;
}

return this.getValue(field) > 0;
return config[field].canBeNull ? config[field].value !== null : config[field].value > 0;
}
return false;
},
Expand All @@ -301,9 +331,18 @@ define([
* @fires minMax#enablemax
*/
enableField: function enableField(field, initialValue) {
if (isFieldSupported(field) && this.is('rendered') && !this.isFieldEnabled(field)) {
if (isFieldSupported(field) && this.is('rendered')) {
const config = this.getConfig();

let valueToSet;
if (config[field].canBeNull) {
valueToSet = initialValue >= 0 ? initialValue : 0;
} else {
valueToSet = initialValue > 1 ? initialValue : 1;
}

controls[field].input
.val(initialValue > 1 ? initialValue : 1)
.val(valueToSet)
.incrementer('enable')
.trigger('change');

Expand Down Expand Up @@ -334,10 +373,13 @@ define([
if (
isFieldSupported(field) &&
this.is('rendered') &&
config[field].toggler === true &&
this.isFieldEnabled(field)
config[field].toggler === true
) {
controls[field].input.val(0).incrementer('disable').trigger('change');
config[field].value = config[field].canBeNull ? null : 0;
controls[field].input
.val(config[field].canBeNull ? '' : 0)
.incrementer('disable')
.trigger('change');

/**
* One of the field is enabled
Expand All @@ -361,10 +403,10 @@ define([
fromField = fromField || fields.min;

if (isNaN(this.getMinValue())) {
this.setMinValue(config.lowerThreshold);
this.setMinValue(this.getLowerThreshold(fromField));
}
if (isNaN(this.getMaxValue())) {
this.setMaxValue(config.lowerThreshold);
this.setMaxValue(this.getLowerThreshold(fromField));
}

if (isFieldSupported(fromField) && this.is('rendered') && config.syncValues) {
Expand All @@ -384,7 +426,7 @@ define([
(document.querySelector('.edit-active > .qti-orderInteraction') ||
document.querySelector('.edit-active > .qti-graphicOrderInteraction'))
) {
this.enableField(fields.min, 1);
this.enableField(fields.min, this.getLowerThreshold(fields.min) || 1);
controls.min.toggler.prop('checked', true);
}
}
Expand All @@ -401,15 +443,23 @@ define([
convertToNumber: function convertToNumber(fromField) {
if (isFieldSupported(fromField) && this.is('rendered')) {
if (fromField === fields.max) {
this.setMaxValue(parseInt(this.getMaxValue()));
this.setMaxValue(this.parseNumber(this.getMaxValue()));
} else {
this.setMinValue(parseInt(this.getMinValue()));
this.setMinValue(this.parseNumber(this.getMinValue()));
}
}

return this;
},

parseNumber: function parseNumber(value) {
const config = this.getConfig();
if (config.allowDecimal) {
return parseFloat(value);
}
return parseInt(value);
},

/**
* disabe toggler
*
Expand Down Expand Up @@ -465,10 +515,14 @@ define([
if (fieldConfig.toggler) {
fieldControl.toggler = $(`[name=${fieldConfig.fieldName}-toggler]`, $element);

//does the toggler starts checked ?
if (fieldConfig.value > 0) {
const shouldEnableField = fieldConfig.canBeNull
? fieldConfig.value !== null
: fieldConfig.value > 0;

if (shouldEnableField) {
fieldControl.toggler.prop('checked', true);
} else {
fieldControl.toggler.prop('checked', false);
self.disableField(field);
}

Expand All @@ -478,7 +532,7 @@ define([
self.enableField(
field,
Math.max(
fieldConfig.lowerThreshold || config.lowerThreshold || 1,
fieldConfig.canBeNull ? 0 : (self.getLowerThreshold(field) || 1),
self.getMinValue()
)
);
Expand All @@ -492,11 +546,7 @@ define([

fieldControl.input.on('change', function () {
self.syncValues(field);

if (!config.allowDecimal) {
self.convertToNumber(field);
}

self.convertToNumber(field);
self.trigger('change');
});
}
Expand Down
23 changes: 16 additions & 7 deletions views/js/qtiCreator/widgets/interactions/helpers/answerState.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,19 +268,27 @@ define([
_toggleCorrectWidgets(defineCorrect);
}

const lowerBoundValue = response.getMappingAttribute('lowerBound');
const upperBoundValue = response.getMappingAttribute('upperBound');
minMaxComponentFactory(widget.$responseForm.find('.response-mapping-attributes > .min-max-panel'), {
min: {
fieldName: 'lowerBound',
value: _.parseInt(response.getMappingAttribute('lowerBound')) || 0,
helpMessage: __('Minimal score for this interaction.')
value: !isNaN(lowerBoundValue) ? parseFloat(lowerBoundValue) : null,
helpMessage: __('Minimal score for this interaction.'),
canBeNull: true,
lowerThreshold: Number.NEGATIVE_INFINITY,
},
max: {
fieldName: 'upperBound',
value: _.parseInt(response.getMappingAttribute('upperBound')) || 0,
helpMessage: __('Maximal score for this interaction.')
value: !isNaN(upperBoundValue) ? parseFloat(upperBoundValue) : null,
helpMessage: __('Maximal score for this interaction.'),
canBeNull: true,
lowerThreshold: 0,
},
upperThreshold: Number.MAX_SAFE_INTEGER,
syncValues: true
lowerThreshold: 0,
syncValues: true,
allowDecimal: true
});

const formChangeCallbacks = {
Expand Down Expand Up @@ -320,8 +328,9 @@ define([
formElement.getLowerUpperAttributeCallbacks('lowerBound', 'upperBound', {
attrMethodNames: {
set: 'setMappingAttribute',
remove: 'removeMappingAttribute'
}
remove: 'removeMappingAttribute',
},
floatVal: true
})
);

Expand Down
7 changes: 7 additions & 0 deletions views/scss/item-creator.scss
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,13 @@ img.dragging.ui-draggable-dragging {
.panel {
padding: 0;
margin-bottom: 15px;

.min-max {
input[name=lowerBound],
input[name=upperBound] {
width: 50px !important;
}
}
}
hr {
margin-bottom: 15px;
Expand Down

0 comments on commit ea41300

Please sign in to comment.