diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a8fdff3a32..9bcc5b0c4e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +## Version 25.03.12 +Features: +- [plugins] Add configuration warning tags to settings UI +- [white-labeling] Add sidebar footer label setting to white labeling + +Fixes: +- [core] Use correct rights validation for loyality +- [crashes] Fix free session for home widget +- [crashes] Fix trend and change calculation for crash stats +- [crashes] Use na for free session and free user when there's no data +- [push] Show segmentation, geo and cohorts related components in push drawer on editing draft. + +Enterprise Fixes: +- [ldap] Error handling in ldap plugin on search error +- [license] Display notification for non global admin user +- [users] Load table data from report if user table calculation goes to report manager + +Dependencies: +- Bump mongodb from 6.17.0 to 6.18.0 +- Bump puppeteer from 24.14.0 to 24.15.0 +- Bump supertest from 7.1.3 to 7.1.4 + + ## Version 25.03.11 Fixes: - [core] Fix mongo connection url parsing @@ -5,6 +28,8 @@ Fixes: - [crashes] Fix free session and free user calculation - [dashboards] Delete associated widgets and reports when a dashboard is removed - [star-rating] Fix widget close post message +- [core] Adjust level and update content of app version log +- [populator] Update getVersion to generate valid semantic version Enterprise Fixes: - [crash_symbolication] Remove auto symbolication setting diff --git a/LICENSE b/LICENSE.md similarity index 92% rename from LICENSE rename to LICENSE.md index 1901e4fc150..0bf57dc9a67 100644 --- a/LICENSE +++ b/LICENSE.md @@ -3,7 +3,7 @@ Countly Product Analytics - Countly Lite License © Countly, https://count.ly -Countly is provided under AGPL v3 with modified Section 7. In accordance +Countly is provided under AGPL-3.0 with modified Section 7. In accordance with Section 7 of the AGPL, the Works included in this package or repository (excluding 3rd party Software), are subject to the following additional terms: diff --git a/README.md b/README.md index 3f4ad6978b4..0ea8dc3416a 100644 --- a/README.md +++ b/README.md @@ -116,3 +116,11 @@ If you like Countly, why not use one of our badges and give a link back to us? Countly - Product Analytics Countly - Product Analytics + + +## License +This project is licensed under **AGPL-3.0** with modified Section 7., see the [LICENSE](LICENSE) file for more details. + +## 💚 Thanks + +This project is tested with BrowserStack. diff --git a/api/parts/data/usage.js b/api/parts/data/usage.js index ce3b2a847d3..0b03e0599de 100644 --- a/api/parts/data/usage.js +++ b/api/parts/data/usage.js @@ -1121,7 +1121,7 @@ plugins.register("/sdk/user_properties", async function(ob) { userProps.av_build = versionComponents.build; } else { - log.w("Invalid app version format: %s", params.qstring.metrics._app_version); + log.d("App version %s is not a valid semantic version. It cannot be separated into semantic version parts", params.qstring.metrics._app_version); userProps.av_major = null; userProps.av_minor = null; userProps.av_patch = null; diff --git a/api/utils/requestProcessor.js b/api/utils/requestProcessor.js index 6a6450f00cc..707eca00467 100644 --- a/api/utils/requestProcessor.js +++ b/api/utils/requestProcessor.js @@ -1567,7 +1567,7 @@ const processRequest = (params) => { common.returnMessage(params, 400, 'Missing parameter "app_id"'); return false; } - validateUserForMgmtReadAPI(countlyApi.mgmt.appUsers.loyalty, params); + validateUserForRead(params, countlyApi.mgmt.appUsers.loyalty); break; } /** diff --git a/bin/scripts/export-data/setting_limits_and_real_values.js b/bin/scripts/export-data/setting_limits_and_real_values.js index 116e97c1744..7cbb0e0bfa3 100644 --- a/bin/scripts/export-data/setting_limits_and_real_values.js +++ b/bin/scripts/export-data/setting_limits_and_real_values.js @@ -4,7 +4,6 @@ * Path: $(countly dir)/bin/scripts/export-data * Command: node setting_limits_and_real_values.js */ - const fs = require('fs'); const crypto = require('crypto'); const common = require('../../../api/utils/common.js'); @@ -20,10 +19,10 @@ const DEFAULT_LIMITS = { view_name_limit: 128, view_segment_limit: 100, view_segment_value_limit: 10, - custom_prop_limit: 20, + //custom_prop_limit: 20, + custom_property_limit: 20, custom_prop_value_limit: 50, }; - Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection("countly_drill")]).then(async function([countlyDb, drillDb]) { console.log("Connected to databases..."); common.db = countlyDb; @@ -36,21 +35,17 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" else { // WRITE START OF ARRAY WriteStream.write('[\n', 'utf8'); - // GETTING DATA FOR SET LIMITS FOR EVENTS, VIEWS, AND CUSTOM PROPERTIES var pluginsCollectionPlugins = await countlyDb.collection("plugins").findOne({"_id": 'plugins'}); - // LOOP APPS FOR EACH REQUIREMENT for (let i = 0; i < apps.length; i++) { var app = apps[i]; console.log(i + 1, ") Processing app:", app.name); - try { var app_results = { "App Name": app.name }, defaultVal, realVal, currentVal; - // SETTING UP CURRENT SET LIMITS PER APP var appsCollectionPerApp = await countlyDb.collection("apps").findOne({"_id": common.db.ObjectID(app._id)}); var CURRENT_LIMITS = { @@ -61,10 +56,10 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" view_name_limit: pluginsCollectionPlugins?.views?.view_name_limit || DEFAULT_LIMITS.view_name_limit, view_segment_limit: pluginsCollectionPlugins?.views?.segment_limit || DEFAULT_LIMITS.view_segment_limit, view_segment_value_limit: pluginsCollectionPlugins?.views?.segment_value_limit || DEFAULT_LIMITS.view_segment_value_limit, - custom_prop_limit: pluginsCollectionPlugins?.users?.custom_prop_limit || DEFAULT_LIMITS.custom_prop_limit, + //custom_prop_limit: pluginsCollectionPlugins?.users?.custom_prop_limit || DEFAULT_LIMITS.custom_prop_limit, + custom_property_limit: pluginsCollectionPlugins?.drill?.custom_property_limit || DEFAULT_LIMITS.custom_property_limit, custom_prop_value_limit: pluginsCollectionPlugins?.users?.custom_set_limit || DEFAULT_LIMITS.custom_prop_value_limit, }; - // GETTING REAL DATA PER APP var eventsCollectionPerApp = await countlyDb.collection("events").findOne({"_id": common.db.ObjectID(app._id)}); var viewsCountsPerApp = await countlyDb.collection("app_viewsmeta" + app._id).countDocuments(); @@ -140,22 +135,15 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" catch (err) { console.log("Mongodb operation failed for app: ", app.name, err); } - // EVENT KEYS defaultVal = DEFAULT_LIMITS.event_limit; - currentVal = CURRENT_LIMITS.event_limit; - let realEvents = eventsCollectionPerApp?.list || []; realVal = realEvents.length; - app_results['Event Keys'] = {"default": defaultVal, "set": currentVal, "real": realVal}; - // SEGMENTS IN ONE EVENT defaultVal = DEFAULT_LIMITS.event_segment_limit; - currentVal = CURRENT_LIMITS.event_segment_limit; - let eventSegments = eventsCollectionPerApp && eventsCollectionPerApp.segments || {}; realVal = Object.entries(eventSegments) .sort((a, b) => b[1].length - a[1].length) @@ -163,23 +151,18 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" acc[key] = value.length; return acc; }, {}); - app_results['Event Segments'] = {"default": defaultVal, "set": currentVal, "real": realVal}; - // UNIQUE EVENT SEGMENT VALUES FOR 1 SEGMENT defaultVal = DEFAULT_LIMITS.event_segment_value_limit; - currentVal = CURRENT_LIMITS.event_segment_value_limit; - realVal = {}; await Promise.all(realEvents.map(async(event) => { var shortEventName = common.fixEventKey(event); - var eventCollectionName = "events" + crypto.createHash('sha1').update(shortEventName + app._id).digest('hex'); - + var hash = crypto.createHash('sha1').update(shortEventName + app._id).digest('hex'); + var eventCollectionName = "events_data"; try { var regexes = [ - "^no-segment_2023:0.*", - "^no-segment_2024:0.*" + "^" + app._id + "_" + hash + "_no-segment_2025:0.*" ]; var eventsSegmentsValues = await countlyDb.collection(eventCollectionName).aggregate([ { @@ -218,7 +201,6 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" } } ]).toArray(); - // Use reduce to transform array eventsSegmentsValues = eventsSegmentsValues.reduce((acc, item) => { const key = item.meta_v2.k; @@ -228,7 +210,6 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" acc[key] += item.meta_v2.v; return acc; }, {}); - if (Object.keys(eventsSegmentsValues).length > 0) { realVal[event] = eventsSegmentsValues; } @@ -238,41 +219,26 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" } })); app_results['Unique Event Segment Values'] = {"default": defaultVal, "set": currentVal, "real": realVal}; - // UNIQUE VIEV NAMES defaultVal = DEFAULT_LIMITS.view_limit; - currentVal = CURRENT_LIMITS.view_limit; - realVal = viewsCountsPerApp; - app_results['Unique View Names'] = {"default": defaultVal, "set": currentVal, "real": realVal}; - // VIEW NAME LENGTH LIMIT defaultVal = DEFAULT_LIMITS.view_name_limit; - currentVal = CURRENT_LIMITS.view_name_limit; - realVal = {longestViewName: "", longestViewLength: 0}; realVal.longestViewName = viewsCollectionPerApp && viewsCollectionPerApp[0] && viewsCollectionPerApp[0]?.view; realVal.longestViewLength = viewsCollectionPerApp && viewsCollectionPerApp[0] && viewsCollectionPerApp[0]?.max_length; - app_results['View Name Length Limit'] = {"default": defaultVal, "set": currentVal, "real": realVal}; - // SEGMENTS IN ONE VIEW defaultVal = DEFAULT_LIMITS.view_segment_limit; - currentVal = CURRENT_LIMITS.view_segment_limit; - realVal = viewsSegmentsPerApp && viewsSegmentsPerApp[0]?.numberOfSegments || 0; - app_results['View Segments'] = {"default": defaultVal, "set": currentVal, "real": realVal}; - // VIEW SEGMENT'S UNIQUE VALUES defaultVal = DEFAULT_LIMITS.view_segment_value_limit; - currentVal = CURRENT_LIMITS.view_segment_value_limit; - realVal = viewsSegmentsPerApp && viewsSegmentsPerApp[0]?.segments || 0; Object.keys(realVal).forEach(key => { if (realVal[key] === 0) { @@ -280,23 +246,18 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" } }); app_results['View Segments Unique Values'] = {"default": defaultVal, "set": currentVal, "real": realVal}; - // USER PROPERTIES - defaultVal = DEFAULT_LIMITS.custom_prop_limit; - - currentVal = CURRENT_LIMITS.custom_prop_limit; - + //defaultVal = DEFAULT_LIMITS.custom_prop_limit; + //currentVal = CURRENT_LIMITS.custom_prop_limit; + defaultVal = DEFAULT_LIMITS.custom_property_limit; + currentVal = CURRENT_LIMITS.custom_property_limit; realVal = customPropsPerApp && customPropsPerApp[0]?.customPropertiesCount || 0; - app_results['Custom User Properties'] = {"default": defaultVal, "set": currentVal, "real": realVal}; - + app_results['Max user custom properties'] = {"default": defaultVal, "set": currentVal, "real": realVal}; // VALUES IN AN ARRAY FOR ONE USER PROPERTY defaultVal = DEFAULT_LIMITS.custom_prop_value_limit; - currentVal = CURRENT_LIMITS.custom_prop_value_limit; - realVal = valueFieldCounts || undefined; app_results['Values In Array For One User Property'] = {"default": defaultVal, "set": currentVal, "real": realVal}; - // WRITE RESULTS PER APP TO FILE WriteStream.write(JSON.stringify(app_results, null, 2), 'utf8'); if (i + 1 < apps.length) { @@ -315,7 +276,6 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" finally { close(); } - async function getAppList(options) { var query = {}; if (app_list && app_list.length > 0) { @@ -325,7 +285,6 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" } query = {_id: {$in: listed}}; } - try { let apps = await options.db.collection("apps").find(query).toArray(); return apps; @@ -334,9 +293,7 @@ Promise.all([pluginManager.dbConnection("countly"), pluginManager.dbConnection(" console.log("Error getting apps: ", err); return []; } - } - function close(err) { if (err) { console.log("Error: ", err); diff --git a/frontend/express/app.js b/frontend/express/app.js index 194ccd85ff6..482b7d91ce1 100644 --- a/frontend/express/app.js +++ b/frontend/express/app.js @@ -422,6 +422,14 @@ Promise.all([plugins.dbConnection(countlyConfig), plugins.dbConnection("countly_ app.loadThemeFiles(curTheme); app.dashboard_headers = plugins.getConfig("security").dashboard_additional_headers; + var overriddenCountlyNamedType = COUNTLY_NAMED_TYPE; + var whiteLabelingConfig = plugins.getConfig("white-labeling"); + if (whiteLabelingConfig && whiteLabelingConfig.footerLabel && whiteLabelingConfig.footerLabel.length) { + overriddenCountlyNamedType = whiteLabelingConfig.footerLabel; + } + + COUNTLY_NAMED_TYPE = overriddenCountlyNamedType; + if (typeof plugins.getConfig('frontend').countly_tracking !== 'boolean' && plugins.isPluginEnabled('tracker')) { plugins.updateConfigs(countlyDb, 'frontend', { countly_tracking: true }); } @@ -929,6 +937,12 @@ Promise.all([plugins.dbConnection(countlyConfig), plugins.dbConnection("countly_ licenseNotification, licenseError; var isLocked = false; configs.export_limit = plugins.getConfig("api").export_limit; + + var currentWhiteLabelingConfig = plugins.getConfig("white-labeling"); + var overriddenCountlyNamedType = COUNTLY_NAMED_TYPE; + if (currentWhiteLabelingConfig && currentWhiteLabelingConfig.footerLabel && currentWhiteLabelingConfig.footerLabel.length) { + overriddenCountlyNamedType = currentWhiteLabelingConfig.footerLabel; + } app.loadThemeFiles(configs.theme, async function(theme) { if (configs._user.theme) { res.cookie("theme", configs.theme); @@ -1004,7 +1018,7 @@ Promise.all([plugins.dbConnection(countlyConfig), plugins.dbConnection("countly_ licenseError, ssr: serverSideRendering, timezones: timezones, - countlyTypeName: COUNTLY_NAMED_TYPE, + countlyTypeName: overriddenCountlyNamedType, countlyTypeTrack: COUNTLY_TRACK_TYPE, countlyTypeCE: COUNTLY_TYPE_CE, countly_tracking, @@ -1037,7 +1051,7 @@ Promise.all([plugins.dbConnection(countlyConfig), plugins.dbConnection("countly_ countlyVersion: req.countly.version, countlyType: COUNTLY_TYPE_CE, countlyTrial: COUNTLY_TRIAL, - countlyTypeName: COUNTLY_NAMED_TYPE, + countlyTypeName: overriddenCountlyNamedType, feedbackLink: COUNTLY_FEEDBACK_LINK, documentationLink: COUNTLY_DOCUMENTATION_LINK, helpCenterLink: COUNTLY_HELPCENTER_LINK, diff --git a/frontend/express/public/javascripts/countly/vue/data/vuex.js b/frontend/express/public/javascripts/countly/vue/data/vuex.js index 6809cd60631..72248ebc465 100644 --- a/frontend/express/public/javascripts/countly/vue/data/vuex.js +++ b/frontend/express/public/javascripts/countly/vue/data/vuex.js @@ -274,14 +274,23 @@ options.onOverrideResponse(context, res); } var convertedResponse = _dataTableAdapters.toStandardResponse(res, requestOptions); - if (!Object.prototype.hasOwnProperty.call(convertedResponse, "echo") || - convertedResponse.echo >= context.state[echoField]) { - if (typeof options.onReady === 'function') { - convertedResponse.rows = options.onReady(context, convertedResponse.rows); + if (res.task_id) { + if (typeof options.onTask === 'function') { + options.onTask(context, res.task_id); } context.commit(_capitalized("set", resourceName), convertedResponse); context.commit(_capitalized("set", lastSuccessfulRequestKey), requestOptions); } + else { + if (!Object.prototype.hasOwnProperty.call(convertedResponse, "echo") || + convertedResponse.echo >= context.state[echoField]) { + if (typeof options.onReady === 'function') { + convertedResponse.rows = options.onReady(context, convertedResponse.rows); + } + context.commit(_capitalized("set", resourceName), convertedResponse); + context.commit(_capitalized("set", lastSuccessfulRequestKey), requestOptions); + } + } }) .catch(function(err) { if (typeof options.onError === 'function') { diff --git a/package-lock.json b/package-lock.json index bb676d5c182..f421c67b686 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,7 +53,7 @@ "method-override": "3.0.0", "moment": "2.30.1", "moment-timezone": "0.6.0", - "mongodb": "6.17.0", + "mongodb": "6.18.0", "nginx-conf": "2.1.0", "nodemailer": "7.0.5", "object-hash": "3.0.0", @@ -83,7 +83,7 @@ "mocha": "10.8.2", "nyc": "17.1.0", "should": "13.2.3", - "supertest": "7.1.3", + "supertest": "7.1.4", "typescript": "^5.8.2" } }, @@ -3629,9 +3629,9 @@ } }, "node_modules/chromium-bidi": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-7.1.1.tgz", - "integrity": "sha512-L2BKQ0rSLADgbPMIdDh3wnYHs3EiUiMay2Sq0CTolheaADmWIf6Pe+T9LJRcnh5rcMz0U7MVk0cQVvKsGRMa1g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-7.2.0.tgz", + "integrity": "sha512-gREyhyBstermK+0RbcJLbFhcQctg92AGgDe/h/taMJEOLRdtSswBAO9KmvltFSQWgM2LrwWu5SIuEUbdm3JsyQ==", "license": "Apache-2.0", "dependencies": { "mitt": "^3.0.1", @@ -3931,6 +3931,7 @@ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -4071,7 +4072,8 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/core-util-is": { "version": "1.0.3", @@ -5500,7 +5502,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { "version": "1.19.1", @@ -9528,9 +9531,9 @@ } }, "node_modules/mongodb": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.17.0.tgz", - "integrity": "sha512-neerUzg/8U26cgruLysKEjJvoNSXhyID3RvzvdcpsIi2COYM3FS3o9nlH7fxFtefTb942dX3W9i37oPfCVj4wA==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.18.0.tgz", + "integrity": "sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==", "license": "Apache-2.0", "dependencies": { "@mongodb-js/saslprep": "^1.1.9", @@ -11103,17 +11106,17 @@ } }, "node_modules/puppeteer": { - "version": "24.14.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.14.0.tgz", - "integrity": "sha512-GB7suRDkp9pUnxpNGAORICQCtw11KFbg6U2iJXVTflzJLK5D1qzq8xOOmLgN/QnDBpDMdpn96ri52XkuN83Giw==", + "version": "24.15.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.15.0.tgz", + "integrity": "sha512-HPSOTw+DFsU/5s2TUUWEum9WjFbyjmvFDuGHtj2X4YUz2AzOzvKMkT3+A3FR+E+ZefiX/h3kyLyXzWJWx/eMLQ==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.10.6", - "chromium-bidi": "7.1.1", + "chromium-bidi": "7.2.0", "cosmiconfig": "^9.0.0", "devtools-protocol": "0.0.1464554", - "puppeteer-core": "24.14.0", + "puppeteer-core": "24.15.0", "typed-query-selector": "^2.12.0" }, "bin": { @@ -11124,13 +11127,13 @@ } }, "node_modules/puppeteer-core": { - "version": "24.14.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.14.0.tgz", - "integrity": "sha512-NO9XpCl+i8oB0zJp81iPhzMo2QK8/JTj4ramSvTpGCo9CPCNo4AZ8qVOGpSgXzlcOfOT3VHOkzTfPo08GOE5jA==", + "version": "24.15.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.15.0.tgz", + "integrity": "sha512-2iy0iBeWbNyhgiCGd/wvGrDSo73emNFjSxYOcyAqYiagkYt5q4cPfVXaVDKBsukgc2fIIfLAalBZlaxldxdDYg==", "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.10.6", - "chromium-bidi": "7.1.1", + "chromium-bidi": "7.2.0", "debug": "^4.4.1", "devtools-protocol": "0.0.1464554", "typed-query-selector": "^2.12.0", @@ -12449,20 +12452,21 @@ } }, "node_modules/superagent": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.2.tgz", - "integrity": "sha512-vWMq11OwWCC84pQaFPzF/VO3BrjkCeewuvJgt1jfV0499Z1QSAWN4EqfMM5WlFDDX9/oP8JjlDKpblrmEoyu4Q==", + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.3.tgz", + "integrity": "sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==", "dev": true, + "license": "MIT", "dependencies": { - "component-emitter": "^1.3.0", + "component-emitter": "^1.3.1", "cookiejar": "^2.1.4", - "debug": "^4.3.4", + "debug": "^4.3.7", "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", + "form-data": "^4.0.4", "formidable": "^3.5.4", "methods": "^1.1.2", "mime": "2.6.0", - "qs": "^6.11.0" + "qs": "^6.11.2" }, "engines": { "node": ">=14.18.0" @@ -12473,6 +12477,7 @@ "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", "dev": true, + "license": "MIT", "dependencies": { "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", @@ -12490,6 +12495,7 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -12498,13 +12504,14 @@ } }, "node_modules/supertest": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.3.tgz", - "integrity": "sha512-ORY0gPa6ojmg/C74P/bDoS21WL6FMXq5I8mawkEz30/zkwdu0gOeqstFy316vHG6OKxqQ+IbGneRemHI8WraEw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.4.tgz", + "integrity": "sha512-tjLPs7dVyqgItVFirHYqe2T+MfWc2VOBQ8QFKKbWTA3PU7liZR8zoSpAi/C1k1ilm9RsXIKYf197oap9wXGVYg==", "dev": true, + "license": "MIT", "dependencies": { "methods": "^1.1.2", - "superagent": "^10.2.2" + "superagent": "^10.2.3" }, "engines": { "node": ">=14.18.0" diff --git a/package.json b/package.json index eeaadca6484..95ddf4ee808 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "mocha": "10.8.2", "nyc": "17.1.0", "should": "13.2.3", - "supertest": "7.1.3", + "supertest": "7.1.4", "typescript": "^5.8.2" }, "dependencies": { @@ -85,7 +85,7 @@ "method-override": "3.0.0", "moment": "2.30.1", "moment-timezone": "0.6.0", - "mongodb": "6.17.0", + "mongodb": "6.18.0", "nginx-conf": "2.1.0", "nodemailer": "7.0.5", "object-hash": "3.0.0", diff --git a/plugins/crashes/frontend/public/javascripts/countly.models.js b/plugins/crashes/frontend/public/javascripts/countly.models.js index 52a14407986..058f6f11aac 100644 --- a/plugins/crashes/frontend/public/javascripts/countly.models.js +++ b/plugins/crashes/frontend/public/javascripts/countly.models.js @@ -152,7 +152,10 @@ function transformAppVersion(inpVersion) { * @param {bool} isPercent - Flag to just format the metric's total values as percentages. */ function populateMetric(metric, isPercent) { - if (dashboard[metric].total !== 0 && dashboard[metric]["prev-total"] !== 0) { + if (dashboard[metric].total === 'NA' || dashboard[metric]['prev-total'] === 'NA') { + dashboard[metric].change = 'NA'; + } + else if (dashboard[metric].total !== 0 && dashboard[metric]["prev-total"] !== 0) { if (isPercent) { dashboard[metric].change = (dashboard[metric].total - dashboard[metric]["prev-total"]).toFixed(1) + "%"; } @@ -166,12 +169,18 @@ function transformAppVersion(inpVersion) { else if (dashboard[metric].total !== 0 && dashboard[metric]["prev-total"] === 0) { dashboard[metric].change = "∞"; } + else if (dashboard[metric].total === dashboard[metric]["prev-total"]) { + dashboard[metric].change = "0"; + } if (dashboard[metric].total === dashboard[metric]["prev-total"]) { dashboard[metric].trend = "n"; } else { - dashboard[metric].trend = dashboard[metric].total >= dashboard[metric]["prev-total"] ? "u" : "d"; + var totl = dashboard[metric].total === 'NA' ? -1 : dashboard[metric].total; + var prevTotl = dashboard[metric]['prev-total'] === 'NA' ? -1 : dashboard[metric]['prev-total']; + + dashboard[metric].trend = totl >= prevTotl ? 'u' : 'd'; } if (metric in derivations) { @@ -182,7 +191,9 @@ function transformAppVersion(inpVersion) { if (isPercent && ["crses", "crnfses", "crfses", "crau", "craunf", "crauf", 'crinv', 'crfinv', 'crnfinv', 'crauinv', 'craufinv', 'craunfinv'].includes(metric)) { ["total", "prev-total"].forEach(function(prop) { - dashboard[metric][prop] = dashboard[metric][prop].toFixed(2) + '%'; + if (dashboard[metric][prop] !== 'NA') { + dashboard[metric][prop] = dashboard[metric][prop].toFixed(2) + '%'; + } }); } } @@ -219,10 +230,13 @@ function transformAppVersion(inpVersion) { } // derive user count from whole users - if (dashboard.crau[prop] > dashboard.cr_u[prop] && 'users' in state.rawData) { + if (dashboard.crau[prop] > dashboard.cr_u[prop] && 'users' in state.rawData && wholeUsers.total > 0) { dashboard.crauf[prop] = dashboard.cr_u[prop] * ((wholeUsers.fatal / wholeUsers.total) - (dashboard.crf[prop] / dashboard.cr_s[prop])); + dashboard.crauf.isEstimate = true; dashboard.craunf[prop] = dashboard.cr_u[prop] * ((wholeUsers.nonfatal / wholeUsers.total) - (dashboard.crnf[prop] / dashboard.cr_s[prop])); + dashboard.craunf.isEstimate = true; dashboard.crau[prop] = dashboard.crauf[prop] + dashboard.craunf[prop]; + dashboard.crau.isEstimate = true; } dashboard.crinv[prop] = Math.max(0, dashboard.cr_s[prop] - dashboard.cr[prop]); @@ -234,9 +248,14 @@ function transformAppVersion(inpVersion) { populateMetric(metric); }); - ["crau", "craunf", "crauf"].forEach(function(name) { - ["total", "prev-total"].forEach(function(prop) { - dashboard[name][prop] = Math.min(100, (dashboard.cr_u[prop] === 0 || dashboard[name][prop] === 0) ? 100 : (Math.abs(dashboard.cr_u[prop] - dashboard[name][prop]) / dashboard.cr_u[prop] * 100)); + ['crau', 'craunf', 'crauf'].forEach(function(name) { + ['total', 'prev-total'].forEach(function(prop) { + if (dashboard.cr_u[prop] === 0 || !Number.isFinite(dashboard[name][prop])) { + dashboard[name][prop] = 'NA'; + } + else { + dashboard[name][prop] = Math.abs(dashboard.cr_u[prop] - dashboard[name][prop]) / dashboard.cr_u[prop] * 100; + } }); populateMetric(name, true); }); @@ -264,17 +283,13 @@ function transformAppVersion(inpVersion) { }); ['crinv', 'crfinv', 'crnfinv'].forEach(function(name) { - ["total", "prev-total"].forEach(function(prop) { - var propValue = 0; - + ['total', 'prev-total'].forEach(function(prop) { if (dashboard.cr_s[prop] === 0) { - propValue = 100; + dashboard[name][prop] = 'NA'; } else { - propValue = dashboard[name][prop] / dashboard.cr_s[prop] * 100; + dashboard[name][prop] = dashboard[name][prop] / dashboard.cr_s[prop] * 100; } - - dashboard[name][prop] = Math.min(100, propValue); }); populateMetric(name, true); }); diff --git a/plugins/crashes/frontend/public/javascripts/countly.views.js b/plugins/crashes/frontend/public/javascripts/countly.views.js index 2f32ce9f589..dcfded97912 100644 --- a/plugins/crashes/frontend/public/javascripts/countly.views.js +++ b/plugins/crashes/frontend/public/javascripts/countly.views.js @@ -1338,7 +1338,7 @@ {"name": CV.i18n('crashes.unique'), "info": CV.i18n('crashes.home.unique'), "prop": "cru", "r": true}, {"name": CV.i18n('crashes.total-per-session'), "info": CV.i18n('crashes.home.per-session'), "prop": "cr-session", "r": true}, {"name": CV.i18n('crashes.free-users'), "info": CV.i18n('crashes.help-free-users'), "prop": "crau", "p": true}, - {"name": CV.i18n('crashes.free-sessions'), "info": CV.i18n('crashes.help-free-sessions'), "prop": "crses", "p": true} + {"name": CV.i18n('crashes.free-sessions'), "info": CV.i18n('crashes.help-free-sessions'), "prop": "crinv", "p": true} ]; for (var k = 0; k < getUs.length; k++) { diff --git a/plugins/plugins/frontend/public/javascripts/countly.models.js b/plugins/plugins/frontend/public/javascripts/countly.models.js index 0b8bf80a186..feffedd6b0a 100644 --- a/plugins/plugins/frontend/public/javascripts/countly.models.js +++ b/plugins/plugins/frontend/public/javascripts/countly.models.js @@ -7,6 +7,7 @@ var _userConfigsData = {}; var _themeList = []; var _graph = {}; + var _configWarnings = null; //Public Methods countlyPlugins.initialize = function() { @@ -307,4 +308,237 @@ }); }; + // Warning types and their associated colors + var WARNING_TYPES = { + DATA_INGESTION: 'dataIngestion', + UI_FILTERING: 'uiFiltering', + SERVER_PERFORMANCE: 'serverPerformance' + // SECURITY_IMPACT: 'securityImpact' // for the 2nd phase + }; + + // Tooltip color mappings + var TOOLTIP_COLORS = { + dataIngestion: { bgColor: '#FCF5E5', textColor: '#E49700' }, + serverPerformance: { bgColor: '#FBECE5', textColor: '#D23F00' }, + uiFiltering: { bgColor: '#E1EFFF', textColor: '#0166D6' } + }; + + /** + * Helper function to create warning objects + * @param {string} type - Warning type + * @param {string} textKey - Warning text key + * @returns {Object} Warning object with type and text + */ + function createWarning(type, textKey) { + return { + type: type, + text: textKey + }; + } + + // Predefined warning combinations + var WARNING_COMBINATIONS = { + DATA_INGESTION: [ + createWarning(WARNING_TYPES.DATA_INGESTION, "configs.tooltip.data-ingestion-warning") + ], + UI_FILTERING: [ + createWarning(WARNING_TYPES.UI_FILTERING, "configs.tooltip.ui-filtering-warning") + ], + SERVER_PERFORMANCE: [ + createWarning(WARNING_TYPES.SERVER_PERFORMANCE, "configs.tooltip.server-performance-warning") + ] + }; + + /** + * Initialize configuration warnings + * @returns {Object} Configuration warnings map + */ + function initializeConfigWarnings() { + if (_configWarnings !== null) { + return _configWarnings; + } + + var configWarnings = { + // API Core Configurations + "api.trim_trailing_ending_spaces": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "api.event_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "api.event_segmentation_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "api.event_segmentation_value_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "api.metric_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "api.session_duration_limit": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "api.array_list_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "api.city_data": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "api.country_data": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + + // Logging Configurations + "logs.default": WARNING_COMBINATIONS.UI_FILTERING, + + // Plugin-specific Configurations + "attribution.segment_value_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + + "crashes.report_limit": [ + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "crashes.max_custom_field_keys": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "crashes.smart_regexes": WARNING_COMBINATIONS.UI_FILTERING, + + "drill.list_limit": [ + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "drill.custom_property_limit": [ + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "drill.projection_limit": [ + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "drill.big_list_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + + "flows.maxDepth": [ + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "flows.nodesCn": [ + ...WARNING_COMBINATIONS.UI_FILTERING + ], + + "hooks.requestLimit": [ + ...WARNING_COMBINATIONS.DATA_INGESTION + ], + + "logger.limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "logger.state": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + + "remote-config.conditions_per_paramaeters": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "remote-config.maximum_allowed_parameters": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + + "sources.sources_length_limit": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + + "users.custom_prop_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "users.custom_set_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + + "views.segment_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "views.segment_value_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "views.view_limit": [ + ...WARNING_COMBINATIONS.SERVER_PERFORMANCE, + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "views.view_name_limit": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + + "data-manager.globalValidationAction": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "data-manager.segmentLevelValidationAction": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ], + "data-manager.enableDataMasking": [ + ...WARNING_COMBINATIONS.DATA_INGESTION, + ...WARNING_COMBINATIONS.UI_FILTERING + ] + }; + + _configWarnings = configWarnings; + return _configWarnings; + } + + countlyPlugins.getConfigWarnings = function(configGroup, key) { + var warnings = initializeConfigWarnings(); + var mapKey = configGroup + "." + key; + return warnings[mapKey] || []; + }; + + countlyPlugins.getTooltipColors = function() { + return TOOLTIP_COLORS; + }; + + countlyPlugins.getTooltipLabel = function(type) { + var labels = { + dataIngestion: CV.i18n('configs.tooltip.data-ingestion'), + uiFiltering: CV.i18n('configs.tooltip.ui-filtering'), + serverPerformance: CV.i18n('configs.tooltip.server-performance') + }; + return labels[type] || 'Unknown Type'; + }; + }(window.countlyPlugins = window.countlyPlugins || {}, jQuery)); diff --git a/plugins/plugins/frontend/public/javascripts/countly.views.js b/plugins/plugins/frontend/public/javascripts/countly.views.js index 9c01f0da1f8..27bae3d1761 100644 --- a/plugins/plugins/frontend/public/javascripts/countly.views.js +++ b/plugins/plugins/frontend/public/javascripts/countly.views.js @@ -534,6 +534,18 @@ getConfigType: function(id) { return this.coreDefaults.includes(id) ? "Core" : "Plugins"; }, + getWarningTags(configGroup, key) { + var warnings = countlyPlugins.getConfigWarnings(configGroup, key); + var tooltipColors = countlyPlugins.getTooltipColors(); + return warnings.map(function(warning) { + return { + tooltipText: CV.i18n(warning.text), + bgColor: tooltipColors[warning.type].bgColor, + textColor: tooltipColors[warning.type].textColor, + label: countlyPlugins.getTooltipLabel(warning.type) + }; + }); + }, checkIfOverwritten: function(id, ns) { ns = ns || this.selectedConfig; var configsData = countlyPlugins.getConfigsData(); diff --git a/plugins/plugins/frontend/public/localization/plugins.properties b/plugins/plugins/frontend/public/localization/plugins.properties index 227e38e26ef..eb10290d9c6 100644 --- a/plugins/plugins/frontend/public/localization/plugins.properties +++ b/plugins/plugins/frontend/public/localization/plugins.properties @@ -243,5 +243,12 @@ configs.help.push-proxyuser = (if needed) Username for proxy server HTTP Basic a configs.help.push-proxypass = (if needed) Password for proxy server HTTP Basic authentication configs.help.push-proxyunauthorized = (if needed) Allow self signed certificates without CA installed +configs.tooltip.server-performance-warning = Adjusting this value may impact system performance +configs.tooltip.data-ingestion-warning = Adjusting this value may affect data processing +configs.tooltip.ui-filtering-warning = Adjusting this value controls how much data is shown in the UI +configs.tooltip.data-ingestion = Data Processing +configs.tooltip.ui-filtering = Interface +configs.tooltip.server-performance = Performance + systemlogs.action.change_configs = Setting Changed systemlogs.action.change_plugins = Plugins Changed diff --git a/plugins/plugins/frontend/public/stylesheets/main.scss b/plugins/plugins/frontend/public/stylesheets/main.scss index 808c8c2a2bd..df5c9b43d8b 100644 --- a/plugins/plugins/frontend/public/stylesheets/main.scss +++ b/plugins/plugins/frontend/public/stylesheets/main.scss @@ -73,6 +73,26 @@ } } +.config-section { + &__header { + width: max-content; + } +} + +.configuration-warning-container { + border-radius: 4px; + display: flex; + height: 20px; + width: auto; + + &__text { + font-size: 10px; + font-weight: 500; + margin: 4px 6px; + text-transform: uppercase; + } +} + .apikey { .el-input { width: 320px; diff --git a/plugins/plugins/frontend/public/templates/configurations.html b/plugins/plugins/frontend/public/templates/configurations.html index e0c933ceb65..49250590e55 100755 --- a/plugins/plugins/frontend/public/templates/configurations.html +++ b/plugins/plugins/frontend/public/templates/configurations.html @@ -51,8 +51,35 @@

-

{{getLabelName(key)}}

-

+
+
+ {{ getLabelName(key) }} +
+
+
+
+ + {{ tag.label }} + +
+
+
+
+

diff --git a/plugins/populator/frontend/public/javascripts/countly.models.js b/plugins/populator/frontend/public/javascripts/countly.models.js index ae043b6efeb..6b1e0484ada 100644 --- a/plugins/populator/frontend/public/javascripts/countly.models.js +++ b/plugins/populator/frontend/public/javascripts/countly.models.js @@ -337,9 +337,13 @@ d = moment(seed); } } - var year = trimYear ? d.format('YY')[1] : d.format('YY'); + + var year = d.format('YY'); + if (trimYear || year[0] === '0') { + year = d.format('YY')[1]; + } var day = parseInt(d.format('DD')[0], 10) === 3 ? 2 : d.format('DD')[0]; - return year + "." + d.format('MM') + "." + day; + return year + '.' + d.format('M') + '.' + day; } /** * @@ -2944,4 +2948,4 @@ }; countlyPopulator.defaultTemplates = defaultTemplates; -}(window.countlyPopulator = window.countlyPopulator || {})); \ No newline at end of file +}(window.countlyPopulator = window.countlyPopulator || {})); diff --git a/plugins/push/frontend/public/javascripts/countly.views.js b/plugins/push/frontend/public/javascripts/countly.views.js index 3988912e029..fc28b17ebf4 100644 --- a/plugins/push/frontend/public/javascripts/countly.views.js +++ b/plugins/push/frontend/public/javascripts/countly.views.js @@ -1122,6 +1122,10 @@ this.setIsLoading(true); countlyPushNotification.service.fetchById(this.id) .then(function(response) { + //Set default settings + response.isEe = (typeof countlySegmentation !== 'undefined'); + response.isGeo = (typeof countlyLocationTargetComponent !== 'undefined'); + response.isCohorts = (typeof countlyCohorts !== 'undefined'); self.setPushNotificationUnderEdit(response); if (self.userCommand === self.UserCommandEnum.DUPLICATE) { self.setId(null); diff --git a/ui-tests/cypress/lib/dashboard/crashes/crashes.js b/ui-tests/cypress/lib/dashboard/crashes/crashes.js index 4c925411fe5..ea66add556e 100644 --- a/ui-tests/cypress/lib/dashboard/crashes/crashes.js +++ b/ui-tests/cypress/lib/dashboard/crashes/crashes.js @@ -563,7 +563,7 @@ const verifyCrashStatisticsEChartElements = ({ cy.verifyElement({ labelElement: crashStatisticsEChartElements.TOTAL_OCCURENCES_CHANGE_VALUE_LABEL, - labelText: "NA", + labelText: "0", }); cy.verifyElement({ @@ -573,7 +573,7 @@ const verifyCrashStatisticsEChartElements = ({ cy.verifyElement({ labelElement: crashStatisticsEChartElements.TOTAL_OCCURENCES_CHANGE_VALUE_LABEL, - labelText: "NA", + labelText: "0", }); cy.verifyElement({ @@ -583,22 +583,22 @@ const verifyCrashStatisticsEChartElements = ({ cy.verifyElement({ labelElement: crashStatisticsEChartElements.CRASH_FREE_USERS_NUMBER_LABEL, - labelText: "100.00%", + labelText: "NA", }); cy.verifyElement({ labelElement: crashStatisticsEChartElements.CRASH_FREE_USERS_CHANGE_VALUE_LABEL, - labelText: "0.0%", + labelText: "NA", }); cy.verifyElement({ labelElement: crashStatisticsEChartElements.CRASH_FREE_SESSIONS_NUMBER_LABEL, - labelText: "100.00%", + labelText: "NA", }); cy.verifyElement({ labelElement: crashStatisticsEChartElements.CRASH_FREE_SESSIONS_CHANGE_VALUE_LABEL, - labelText: "0.0%", + labelText: "NA", }); return; } @@ -686,4 +686,4 @@ module.exports = { verifyCrashGroupsDataFromTable, verifyCrashStatisticsMetricCard, verifyCrashStatisticsEChartElements -}; \ No newline at end of file +}; diff --git a/ui-tests/cypress/lib/dashboard/home/home.js b/ui-tests/cypress/lib/dashboard/home/home.js index c77f4e8dff0..83a9cd9a7c9 100644 --- a/ui-tests/cypress/lib/dashboard/home/home.js +++ b/ui-tests/cypress/lib/dashboard/home/home.js @@ -484,7 +484,7 @@ const verifyEmptyPageElements = () => { cy.verifyElement({ element: homePageElements.CRASH_STATISTICS.TOTAL_CRASHES_TREND_VALUE, - elementText: "NA", + elementText: "0", }); cy.verifyElement({ @@ -498,7 +498,7 @@ const verifyEmptyPageElements = () => { cy.verifyElement({ element: homePageElements.CRASH_STATISTICS.UNIQUE_CRASHES_TREND_VALUE, - elementText: "NA", + elementText: "0", }); cy.verifyElement({ @@ -512,7 +512,7 @@ const verifyEmptyPageElements = () => { cy.verifyElement({ element: homePageElements.CRASH_STATISTICS.CRASH_FREE_USERS_NUMBER, - elementText: "100.00%", + elementText: "NA", }); cy.verifyElement({ @@ -521,12 +521,12 @@ const verifyEmptyPageElements = () => { cy.verifyElement({ element: homePageElements.CRASH_STATISTICS.CRASH_FREE_USERS_TREND_VALUE, - elementText: "0.0%", + elementText: "NA", }); cy.verifyElement({ element: homePageElements.CRASH_STATISTICS.CRASH_FREE_SESSIONS_NUMBER, - elementText: "100.00%", + elementText: "NA", }); cy.verifyElement({ @@ -535,7 +535,7 @@ const verifyEmptyPageElements = () => { cy.verifyElement({ element: homePageElements.CRASH_STATISTICS.CRASH_FREE_SESSIONS_TREND_VALUE, - elementText: "0.0%", + elementText: "NA", }); }; @@ -806,4 +806,4 @@ const verifyFullDataPageElements = () => { module.exports = { verifyEmptyPageElements, verifyFullDataPageElements -}; \ No newline at end of file +}; diff --git a/ui-tests/cypress/lib/dashboard/manage/configurations/configurations.js b/ui-tests/cypress/lib/dashboard/manage/configurations/configurations.js index 558de3b930d..d2a9f7d4480 100644 --- a/ui-tests/cypress/lib/dashboard/manage/configurations/configurations.js +++ b/ui-tests/cypress/lib/dashboard/manage/configurations/configurations.js @@ -179,13 +179,13 @@ const verifyPageElements = () => { attrText: "100" }); + cy.scrollPageToCenter(); + cy.verifyElement({ labelElement: configurationsListBoxElements({subFeature: SETTINGS.API.DATA_LIMITS.EVENT_SEGMENTATION_VALUE_LIMIT}).SELECTED_SUBFEATURE_TITLE, labelText: "Max unique values in each segmentation", }); - cy.scrollPageToCenter(); - cy.verifyElement({ labelElement: configurationsListBoxElements({subFeature: SETTINGS.API.DATA_LIMITS.EVENT_SEGMENTATION_VALUE_LIMIT}).SELECTED_SUBFEATURE_DESCRIPTION, labelText: "Maximum number of unique values in each segmentation. Increasing this number may affect your server performance.",