Bläddra i källkod

Split Tests Admin UI - test list (#6411)

* Admin page to list split tests

Admin page to list split tests

Update split test model

Display optional split test fields + Only display link in admin menu in SaaS mode

Add a separate endpoint to update split test info (to avoid creating a new version)

Fix split test tests after rebase

Add name and activeOnly filtering to split test list

Sort split tests by descending order of last modification

Fix lint build error

Add buttons to copy variant assignment as query string

* Move react components to follow our file structure guidelines

* Cleanup and improvements from review

* Small change of report URLs display

* Improve filters display for small screens

GitOrigin-RevId: 498531a1f080419de017883e33d6afed05a3f5c9
Alexandre Bourdin 4 år sedan
förälder
incheckning
931c53d04c

+ 33 - 8
services/web/app/src/Features/SplitTests/SplitTestManager.js

@@ -6,9 +6,16 @@ const ALPHA_PHASE = 'alpha'
 const BETA_PHASE = 'beta'
 const BETA_PHASE = 'beta'
 const RELEASE_PHASE = 'release'
 const RELEASE_PHASE = 'release'
 
 
-async function getSplitTests() {
+async function getSplitTests({ name, activeOnly }) {
+  const filters = {}
+  if (name && name !== '') {
+    filters.name = { $regex: _.escapeRegExp(name) }
+  }
+  if (activeOnly) {
+    filters.$where = 'this.versions[this.versions.length - 1].active === true'
+  }
   try {
   try {
-    return await SplitTest.find().exec()
+    return await SplitTest.find(filters).limit(100).exec()
   } catch (error) {
   } catch (error) {
     throw OError.tag(error, 'Failed to get split tests list')
     throw OError.tag(error, 'Failed to get split tests list')
   }
   }
@@ -22,14 +29,13 @@ async function getSplitTestByName(name) {
   }
   }
 }
 }
 
 
-async function createSplitTest(name, configuration) {
+async function createSplitTest(name, configuration, info = {}) {
   const stripedVariants = []
   const stripedVariants = []
   let stripeStart = 0
   let stripeStart = 0
   _checkNewVariantsConfiguration([], configuration.variants)
   _checkNewVariantsConfiguration([], configuration.variants)
   for (const variant of configuration.variants) {
   for (const variant of configuration.variants) {
     stripedVariants.push({
     stripedVariants.push({
       name: variant.name,
       name: variant.name,
-      active: variant.active,
       rolloutPercent: variant.rolloutPercent,
       rolloutPercent: variant.rolloutPercent,
       rolloutStripes: [
       rolloutStripes: [
         {
         {
@@ -42,6 +48,11 @@ async function createSplitTest(name, configuration) {
   }
   }
   const splitTest = new SplitTest({
   const splitTest = new SplitTest({
     name,
     name,
+    description: info.description,
+    expectedEndDate: info.expectedEndDate,
+    ticketUrl: info.ticketUrl,
+    reportsUrls: info.reportsUrls,
+    winningVariant: info.winningVariant,
     versions: [
     versions: [
       {
       {
         versionNumber: 1,
         versionNumber: 1,
@@ -54,7 +65,7 @@ async function createSplitTest(name, configuration) {
   return _saveSplitTest(splitTest)
   return _saveSplitTest(splitTest)
 }
 }
 
 
-async function updateSplitTest(name, configuration) {
+async function updateSplitTestConfig(name, configuration) {
   const splitTest = await getSplitTestByName(name)
   const splitTest = await getSplitTestByName(name)
   if (splitTest) {
   if (splitTest) {
     const lastVersion = splitTest.getCurrentVersion().toObject()
     const lastVersion = splitTest.getCurrentVersion().toObject()
@@ -68,6 +79,7 @@ async function updateSplitTest(name, configuration) {
       lastVersion.variants,
       lastVersion.variants,
       configuration.variants
       configuration.variants
     )
     )
+
     splitTest.versions.push({
     splitTest.versions.push({
       versionNumber: lastVersion.versionNumber + 1,
       versionNumber: lastVersion.versionNumber + 1,
       phase: configuration.phase,
       phase: configuration.phase,
@@ -80,6 +92,20 @@ async function updateSplitTest(name, configuration) {
   }
   }
 }
 }
 
 
+async function updateSplitTestInfo(name, info) {
+  const splitTest = await getSplitTestByName(name)
+  if (splitTest) {
+    splitTest.description = info.description
+    splitTest.expectedEndDate = info.expectedEndDate
+    splitTest.ticketUrl = info.ticketUrl
+    splitTest.reportsUrls = info.reportsUrls
+    splitTest.winningVariant = info.winningVariant
+    return _saveSplitTest(splitTest)
+  } else {
+    throw new OError(`Cannot update split test '${name}': not found`)
+  }
+}
+
 async function switchToNextPhase(name) {
 async function switchToNextPhase(name) {
   const splitTest = await getSplitTestByName(name)
   const splitTest = await getSplitTestByName(name)
   if (splitTest) {
   if (splitTest) {
@@ -181,7 +207,6 @@ function _updateVariantsWithNewConfiguration(
     if (!variant) {
     if (!variant) {
       variantsCopy.push({
       variantsCopy.push({
         name: newVariantConfig.name,
         name: newVariantConfig.name,
-        active: newVariantConfig.active,
         rolloutPercent: newVariantConfig.rolloutPercent,
         rolloutPercent: newVariantConfig.rolloutPercent,
         rolloutStripes: [
         rolloutStripes: [
           {
           {
@@ -194,7 +219,6 @@ function _updateVariantsWithNewConfiguration(
     } else if (variant.rolloutPercent < newVariantConfig.rolloutPercent) {
     } else if (variant.rolloutPercent < newVariantConfig.rolloutPercent) {
       const newStripeSize =
       const newStripeSize =
         newVariantConfig.rolloutPercent - variant.rolloutPercent
         newVariantConfig.rolloutPercent - variant.rolloutPercent
-      variant.active = newVariantConfig.active
       variant.rolloutPercent = newVariantConfig.rolloutPercent
       variant.rolloutPercent = newVariantConfig.rolloutPercent
       variant.rolloutStripes.push({
       variant.rolloutStripes.push({
         start: totalRolloutPercentage,
         start: totalRolloutPercentage,
@@ -224,7 +248,8 @@ module.exports = {
   getSplitTestByName,
   getSplitTestByName,
   getSplitTests,
   getSplitTests,
   createSplitTest,
   createSplitTest,
-  updateSplitTest,
+  updateSplitTestConfig,
+  updateSplitTestInfo,
   switchToNextPhase,
   switchToNextPhase,
   revertToPreviousVersion,
   revertToPreviousVersion,
 }
 }

+ 21 - 5
services/web/app/src/models/SplitTest.js

@@ -30,11 +30,6 @@ const VariantSchema = new Schema(
         message: `invalid, cannot be 'default' and must match: ${NAME_REGEX}, got {VALUE}`,
         message: `invalid, cannot be 'default' and must match: ${NAME_REGEX}, got {VALUE}`,
       },
       },
     },
     },
-    active: {
-      type: Boolean,
-      default: true,
-      required: true,
-    },
     rolloutPercent: RolloutPercentType,
     rolloutPercent: RolloutPercentType,
     rolloutStripes: [
     rolloutStripes: [
       {
       {
@@ -93,6 +88,27 @@ const SplitTestSchema = new Schema({
     type: Boolean,
     type: Boolean,
     required: false,
     required: false,
   },
   },
+  description: {
+    type: String,
+    required: false,
+  },
+  expectedEndDate: {
+    type: Date,
+    required: false,
+  },
+  ticketUrl: {
+    type: String,
+    required: false,
+  },
+  reportsUrls: {
+    type: [String],
+    required: false,
+    default: [],
+  },
+  winningVariant: {
+    type: String,
+    required: false,
+  },
 })
 })
 
 
 SplitTestSchema.methods.getCurrentVersion = function () {
 SplitTestSchema.methods.getCurrentVersion = function () {

+ 3 - 0
services/web/app/views/layout/navbar-marketing.pug

@@ -33,6 +33,9 @@ nav.navbar.navbar-default.navbar-main
 								a(href="/admin") Manage Site
 								a(href="/admin") Manage Site
 							li
 							li
 								a(href="/admin/user") Manage Users
 								a(href="/admin/user") Manage Users
+							if hasFeature('saas')
+								li
+									a(href="/admin/split-test") Manage Split Tests
 
 
 
 
 				// loop over header_extras
 				// loop over header_extras

+ 3 - 0
services/web/app/views/layout/navbar.pug

@@ -23,6 +23,9 @@ nav.navbar.navbar-default.navbar-main
 								a(href="/admin") Manage Site
 								a(href="/admin") Manage Site
 							li
 							li
 								a(href="/admin/user") Manage Users
 								a(href="/admin/user") Manage Users
+							if hasFeature('saas')
+								li
+									a(href="/admin/split-test") Manage Split Tests
 
 
 
 
 				// loop over header_extras
 				// loop over header_extras