mirror of
https://github.com/overleaf/overleaf.git
synced 2024-10-24 21:12:38 -04:00
cfaec97a3d
Backfill User Properties GitOrigin-RevId: ea2ffeaaf71d5ce41c76a1bfb2f0014006ef0d08
114 lines
3.2 KiB
JavaScript
114 lines
3.2 KiB
JavaScript
const _ = require('lodash')
|
|
const Settings = require('@overleaf/settings')
|
|
|
|
/**
|
|
* Merge feature sets coming from different sources
|
|
*/
|
|
function mergeFeatures(featuresA, featuresB) {
|
|
const features = Object.assign({}, featuresA)
|
|
for (const key in featuresB) {
|
|
// Special merging logic for non-boolean features
|
|
if (key === 'compileGroup') {
|
|
if (
|
|
features.compileGroup === 'priority' ||
|
|
featuresB.compileGroup === 'priority'
|
|
) {
|
|
features.compileGroup = 'priority'
|
|
} else {
|
|
features.compileGroup = 'standard'
|
|
}
|
|
} else if (key === 'collaborators') {
|
|
if (features.collaborators === -1 || featuresB.collaborators === -1) {
|
|
features.collaborators = -1
|
|
} else {
|
|
features.collaborators = Math.max(
|
|
features.collaborators || 0,
|
|
featuresB.collaborators || 0
|
|
)
|
|
}
|
|
} else if (key === 'compileTimeout') {
|
|
features.compileTimeout = Math.max(
|
|
features.compileTimeout || 0,
|
|
featuresB.compileTimeout || 0
|
|
)
|
|
} else {
|
|
// Boolean keys, true is better
|
|
features[key] = features[key] || featuresB[key]
|
|
}
|
|
}
|
|
if (features.mendeley && features.referencesSearch && features.zotero) {
|
|
// Back fill legacy feature flag for isFeatureSetBetter to work properly
|
|
// with professional feature overrides.
|
|
features.references = true
|
|
}
|
|
return features
|
|
}
|
|
|
|
/**
|
|
* Returns whether `featuresA` is a better feature set than `featuresB`
|
|
*/
|
|
function isFeatureSetBetter(featuresA, featuresB) {
|
|
const mergedFeatures = mergeFeatures(featuresA, featuresB)
|
|
return _.isEqual(featuresA, mergedFeatures)
|
|
}
|
|
|
|
/**
|
|
* Return what's missing from `currentFeatures` to equal `expectedFeatures`
|
|
*/
|
|
function compareFeatures(currentFeatures, expectedFeatures) {
|
|
currentFeatures = _.clone(currentFeatures)
|
|
expectedFeatures = _.clone(expectedFeatures)
|
|
if (_.isEqual(currentFeatures, expectedFeatures)) {
|
|
return {}
|
|
}
|
|
|
|
const mismatchReasons = {}
|
|
const featureKeys = [
|
|
...new Set([
|
|
...Object.keys(currentFeatures),
|
|
...Object.keys(expectedFeatures),
|
|
]),
|
|
]
|
|
featureKeys.sort().forEach(key => {
|
|
if (expectedFeatures[key] !== currentFeatures[key]) {
|
|
mismatchReasons[key] = expectedFeatures[key]
|
|
}
|
|
})
|
|
|
|
if (mismatchReasons.compileTimeout) {
|
|
// store the compile timeout difference instead of the new compile timeout
|
|
mismatchReasons.compileTimeout =
|
|
expectedFeatures.compileTimeout - currentFeatures.compileTimeout
|
|
}
|
|
|
|
if (mismatchReasons.collaborators) {
|
|
// store the collaborators difference instead of the new number only
|
|
// replace -1 by 100 to make it clearer
|
|
if (expectedFeatures.collaborators === -1) {
|
|
expectedFeatures.collaborators = 100
|
|
}
|
|
if (currentFeatures.collaborators === -1) {
|
|
currentFeatures.collaborators = 100
|
|
}
|
|
mismatchReasons.collaborators =
|
|
expectedFeatures.collaborators - currentFeatures.collaborators
|
|
}
|
|
|
|
return mismatchReasons
|
|
}
|
|
|
|
function getMatchedFeatureSet(features) {
|
|
for (const [name, featureSet] of Object.entries(Settings.features)) {
|
|
if (_.isEqual(features, featureSet)) {
|
|
return name
|
|
}
|
|
}
|
|
return 'mixed'
|
|
}
|
|
|
|
module.exports = {
|
|
mergeFeatures,
|
|
isFeatureSetBetter,
|
|
compareFeatures,
|
|
getMatchedFeatureSet,
|
|
}
|