Fix sorting of settings

_.sortBy works improperly when returning array as a sorter.
Numbers are sorted as strings in this case.

Closes-Bug: #1644461

Change-Id: I7642ae2af6b847bd7c3217700f6866c2aef307c9
This commit is contained in:
Julia Aranovich 2016-12-05 11:38:03 +03:00
parent fcf4afcc39
commit 6c1c688e37
6 changed files with 84 additions and 69 deletions

View File

@ -951,6 +951,10 @@ models.Settings = BaseModel
} }
}); });
this.isValid({models}); this.isValid({models});
},
sortAttributes({weight: weight1, label: label1}, {weight: weight2, label: label2}) {
if (weight1 !== weight2) return weight1 - weight2;
return utils.natsort(label1, label2);
} }
}); });

View File

@ -1569,47 +1569,49 @@ var NetworkSettings = React.createClass({
return ( return (
<div className='forms-box network'> <div className='forms-box network'>
{ {
_.chain(settings.attributes) _.chain(
.keys() _.keys(settings.attributes).sort(
.filter( (sectionName1, sectionName2) => settings.sortAttributes(
(sectionName) => { settings.get(sectionName1 + '.metadata'),
var section = settings.get(sectionName); settings.get(sectionName2 + '.metadata')
return (section.metadata.group === 'network' || )
_.some(section, {group: 'network'})) &&
!this.checkRestrictions('hide', section.metadata).result;
}
) )
.sortBy((sectionName) => { )
var {weight, label} = settings.get(sectionName + '.metadata'); .filter(
return [weight, label]; (sectionName) => {
}) var section = settings.get(sectionName);
.map( return (section.metadata.group === 'network' ||
(sectionName) => { _.some(section, {group: 'network'})) &&
var section = settings.get(sectionName); !this.checkRestrictions('hide', section.metadata).result;
var settingsToDisplay = _.compact(_.map(section, (setting, settingName) => }
(section.metadata.group || setting.group === 'network') && )
settings.isSettingVisible(setting, settingName, this.props.configModels) && .map(
settingName (sectionName) => {
)); var section = settings.get(sectionName);
if (_.isEmpty(settingsToDisplay) && !settings.isPlugin(section)) return null; var settingsToDisplay = _.compact(_.map(section, (setting, settingName) =>
return <SettingSection (section.metadata.group || setting.group === 'network') &&
{... _.pick( settings.isSettingVisible(setting, settingName, this.props.configModels) &&
this.props, settingName
'cluster', 'initialAttributes', 'settingsForChecks', 'configModels' ));
)} if (_.isEmpty(settingsToDisplay) && !settings.isPlugin(section)) return null;
key={sectionName} return <SettingSection
sectionName={sectionName} {... _.pick(
settingsToDisplay={settingsToDisplay} this.props,
onChange={_.partial(this.onChange, sectionName)} 'cluster', 'initialAttributes', 'settingsForChecks', 'configModels'
allocatedRoles={allocatedRoles} )}
settings={settings} key={sectionName}
getValueAttribute={settings.getValueAttribute} sectionName={sectionName}
locked={locked} settingsToDisplay={settingsToDisplay}
checkRestrictions={this.checkRestrictions} onChange={_.partial(this.onChange, sectionName)}
/>; allocatedRoles={allocatedRoles}
} settings={settings}
) getValueAttribute={settings.getValueAttribute}
.value() locked={locked}
checkRestrictions={this.checkRestrictions}
/>;
}
)
.value()
} }
</div> </div>
); );

View File

@ -1206,11 +1206,13 @@ var NodeInterface = React.createClass({
attributes.get(utils.makePath(sectionName, 'metadata')) attributes.get(utils.makePath(sectionName, 'metadata'))
).result ).result
) )
.sortBy((sectionName) => { .value()
var {weight, label} = attributes.get(sectionName + '.metadata'); .sort(
return [weight, label]; (sectionName1, sectionName2) => attributes.sortAttributes(
}) attributes.get(sectionName1 + '.metadata'),
.value(); attributes.get(sectionName2 + '.metadata')
)
);
var bondingPossible = !!availableBondingTypes.length && !configurationTemplateExists && !locked; var bondingPossible = !!availableBondingTypes.length && !configurationTemplateExists && !locked;
var networkErrors = (_.flatten((errors || {}).networks || [])).join(', '); var networkErrors = (_.flatten((errors || {}).networks || [])).join(', ');
@ -1565,19 +1567,19 @@ var NodeInterfaceAttributes = React.createClass({
// the following code provides the following suggestion: // the following code provides the following suggestion:
// first setting in NIC's attribute section should be a checkbox // first setting in NIC's attribute section should be a checkbox
// that reflects enableness of the section on the particular NIC // that reflects enableness of the section on the particular NIC
var name = _.chain(_.keys(attributes.get(sectionName))) var name = _.find(
.sortBy((settingName) => { _.keys(attributes.get(sectionName)).sort(
var {weight, label} = attributes.get(utils.makePath(sectionName, settingName)); (settingName1, settingName2) => attributes.sortAttributes(
return [weight, label]; attributes.get(utils.makePath(sectionName, settingName1)),
}) attributes.get(utils.makePath(sectionName, settingName2))
.find(
(settingName) => attributes.isSettingVisible(
attributes.get(utils.makePath(sectionName, settingName)),
settingName,
configModels
) )
),
(settingName) => attributes.isSettingVisible(
attributes.get(utils.makePath(sectionName, settingName)),
settingName,
configModels
) )
.value(); );
var value = attributes.get(utils.makePath(sectionName, name, 'value')); var value = attributes.get(utils.makePath(sectionName, name, 'value'));
if (_.isBoolean(value)) { if (_.isBoolean(value)) {

View File

@ -269,10 +269,12 @@ var SettingSection = React.createClass({
var isPluginWithLegacyTasksLocked = isPlugin && metadata.contains_legacy_tasks && var isPluginWithLegacyTasksLocked = isPlugin && metadata.contains_legacy_tasks &&
!settings.get('common.propagate_task_deploy.value'); !settings.get('common.propagate_task_deploy.value');
var sortedSettings = _.sortBy(settingsToDisplay, (settingName) => { var sortedSettings = settingsToDisplay.sort(
var {weight, label} = section[settingName]; (settingName1, settingName2) => settings.sortAttributes(
return [weight, label]; section[settingName1],
}); section[settingName2]
)
);
var processedGroupRestrictions = this.processRestrictions(metadata); var processedGroupRestrictions = this.processRestrictions(metadata);
var processedGroupDependencies = this.checkDependencies(sectionName, 'metadata'); var processedGroupDependencies = this.checkDependencies(sectionName, 'metadata');
var isGroupDisabled = locked || var isGroupDisabled = locked ||

View File

@ -304,10 +304,12 @@ var SettingsTab = React.createClass({
{_.map(groupedSettings, (selectedGroup, groupName) => { {_.map(groupedSettings, (selectedGroup, groupName) => {
if (groupName !== activeSettingsSectionName) return null; if (groupName !== activeSettingsSectionName) return null;
var sortedSections = _.sortBy(_.keys(selectedGroup), (sectionName) => { var sortedSections = _.keys(selectedGroup).sort(
var {weight, label} = settings.get(sectionName + '.metadata'); (sectionName1, sectionName2) => settings.sortAttributes(
return [weight, label]; settings.get(sectionName1 + '.metadata'),
}); settings.get(sectionName2 + '.metadata')
)
);
return ( return (
<div className={'col-xs-10 forms-box ' + groupName} key={groupName}> <div className={'col-xs-10 forms-box ' + groupName} key={groupName}>
{_.map(sortedSections, (sectionName) => { {_.map(sortedSections, (sectionName) => {

View File

@ -1678,7 +1678,14 @@ export var ShowNodeInfoDialog = React.createClass({
var isLocked = !node.get('pending_addition') || actionInProgress; var isLocked = !node.get('pending_addition') || actionInProgress;
var attributes = _.chain(_.keys(nodeAttributes.attributes)) var attributes = _.chain(
_.keys(nodeAttributes.attributes).sort(
(sectionName1, sectionName2) => nodeAttributes.sortAttributes(
nodeAttributes.get(sectionName1 + '.metadata'),
nodeAttributes.get(sectionName2 + '.metadata')
)
)
)
.filter( .filter(
(sectionName) => !nodeAttributes.checkRestrictions( (sectionName) => !nodeAttributes.checkRestrictions(
configModels, configModels,
@ -1686,10 +1693,6 @@ export var ShowNodeInfoDialog = React.createClass({
nodeAttributes.get(sectionName).metadata nodeAttributes.get(sectionName).metadata
).result ).result
) )
.sortBy((sectionName) => {
var {weight, label} = nodeAttributes.get(sectionName + '.metadata');
return [weight, label];
})
.map( .map(
(sectionName) => { (sectionName) => {
var metadata = nodeAttributes.get(utils.makePath(sectionName, 'metadata')); var metadata = nodeAttributes.get(utils.makePath(sectionName, 'metadata'));