Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: new logic for minMax component: min value can be 0 #2611

Merged
merged 9 commits into from
Dec 11, 2024
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
taopkorczak marked this conversation as resolved.
Show resolved Hide resolved
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,
taopkorczak marked this conversation as resolved.
Show resolved Hide resolved
},
taopkorczak marked this conversation as resolved.
Show resolved Hide resolved
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);
taopkorczak marked this conversation as resolved.
Show resolved Hide resolved
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
Loading