Add Experiments -- helps to toggle experiment variation

This commit is contained in:
Moon 2022-02-17 12:29:53 -08:00
parent 144ab092dd
commit e8261ca7e6
10 changed files with 216 additions and 12 deletions

View File

@ -10,8 +10,9 @@ import { applyFilters } from '@wordpress/hooks';
import { AdminNotes } from '../admin-notes'; import { AdminNotes } from '../admin-notes';
import { default as Tools } from '../tools'; import { default as Tools } from '../tools';
import { default as Options } from '../options'; import { default as Options } from '../options';
import { default as Experiments } from '../experiments';
const tabs = applyFilters( 'woocommerce_admin_test_helper_tabs', [ const tabs = applyFilters('woocommerce_admin_test_helper_tabs', [
{ {
name: 'options', name: 'options',
title: 'Options', title: 'Options',
@ -27,7 +28,12 @@ const tabs = applyFilters( 'woocommerce_admin_test_helper_tabs', [
title: 'Tools', title: 'Tools',
content: <Tools />, content: <Tools />,
}, },
] ); {
name: 'experiments',
title: 'Experiments',
content: <Experiments />,
},
]);
export function App() { export function App() {
return ( return (
@ -36,18 +42,18 @@ export function App() {
<TabPanel <TabPanel
className="woocommerce-admin-test-helper__main-tab-panel" className="woocommerce-admin-test-helper__main-tab-panel"
activeClass="active-tab" activeClass="active-tab"
tabs={ tabs } tabs={tabs}
initialTabName={ tabs[ 0 ].name } initialTabName={tabs[0].name}
> >
{ ( tab ) => ( {(tab) => (
<> <>
{ tab.content } {tab.content}
{ applyFilters( {applyFilters(
`woocommerce_admin_test_helper_tab_${ tab.name }`, `woocommerce_admin_test_helper_tab_${tab.name}`,
[] []
) } )}
</> </>
) } )}
</TabPanel> </TabPanel>
</div> </div>
); );

View File

@ -0,0 +1,6 @@
const TYPES = {
TOGGLE_EXPERIMENT: 'TOGGLE_EXPERIMENT',
SET_EXPERIMENTS: 'SET_EXPERIMENTS',
};
export default TYPES;

View File

@ -0,0 +1,34 @@
/**
* Internal dependencies
*/
import TYPES from './action-types';
import { EXPERIMENT_NAME_PREFIX } from './constants';
export function toggleExperiment(experimentName) {
const storageItem = JSON.parse(
window.localStorage.getItem(EXPERIMENT_NAME_PREFIX + experimentName)
);
const newVariation =
storageItem.variationName === 'control' ? 'treatment' : 'control';
storageItem.variationName = newVariation;
window.localStorage.setItem(
EXPERIMENT_NAME_PREFIX + experimentName,
JSON.stringify(storageItem)
);
return {
type: TYPES.TOGGLE_EXPERIMENT,
experimentName,
newVariation,
};
}
export function setExperiments(experiments) {
return {
type: TYPES.SET_EXPERIMENTS,
experiments,
};
}

View File

@ -0,0 +1,2 @@
export const STORE_KEY = 'wc-admin-helper/experiments';
export const EXPERIMENT_NAME_PREFIX = 'explat-experiment--';

View File

@ -0,0 +1,22 @@
/**
* External dependencies
*/
import { registerStore } from '@wordpress/data';
import { controls } from '@wordpress/data-controls';
/**
* Internal dependencies
*/
import * as actions from './actions';
import * as resolvers from './resolvers';
import * as selectors from './selectors';
import reducer from './reducer';
import { STORE_KEY } from './constants';
export default registerStore(STORE_KEY, {
actions,
selectors,
resolvers,
controls,
reducer,
});

View File

@ -0,0 +1,34 @@
/**
* Internal dependencies
*/
import TYPES from './action-types';
const DEFAULT_STATE = {
experiments: [],
};
const reducer = (state = DEFAULT_STATE, action) => {
switch (action.type) {
case TYPES.TOGGLE_EXPERIMENT:
let experiments = [...state.experiments];
experiments = experiments.map((experiment) => {
if (experiment.name === action.experimentName) {
experiment.variation = action.newVariation;
}
return experiment;
});
return {
...state,
experiments,
};
case TYPES.SET_EXPERIMENTS:
return {
...state,
experiments: action.experiments,
};
default:
return state;
}
};
export default reducer;

View File

@ -0,0 +1,32 @@
/**
* Internal dependencies
*/
import { setExperiments } from './actions';
import { EXPERIMENT_NAME_PREFIX } from './constants';
export function* getExperiments() {
const storageItems = Object.entries({ ...window.localStorage }).filter(
(item) => {
if (item[0].indexOf(EXPERIMENT_NAME_PREFIX) === 0) {
return true;
}
return false;
}
);
const experiments = [];
storageItems.forEach((storageItem) => {
const [key, value] = storageItem;
const objectValue = JSON.parse(value);
const experiment = {
name: key.replace(EXPERIMENT_NAME_PREFIX, ''),
variation: objectValue.variationName
? objectValue.variationName
: 'control',
};
experiments.push(experiment);
});
yield setExperiments(experiments);
}

View File

@ -0,0 +1,3 @@
export function getExperiments(state) {
return state.experiments;
}

65
src/experiments/index.js Normal file
View File

@ -0,0 +1,65 @@
/**
* External dependencies
*/
import { withDispatch, withSelect } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { Button } from '@wordpress/components';
/**
* Internal dependencies
*/
import { STORE_KEY } from './data/constants';
import './data';
function Experiments({ experiments, toggleExperiment }) {
return (
<div id="wc-admin-test-helper-experiments">
<h2>Experiments</h2>
<table className="experiments wp-list-table striped table-view-list widefat">
<thead>
<tr>
<th>Experiment</th>
<th>Variation</th>
<th>Toggle</th>
</tr>
</thead>
<tbody>
{experiments.map(({ name, variation }, index) => {
return (
<tr key={index}>
<td className="experiment-name">{name}</td>
<td align="center">{variation}</td>
<td align="center">
<Button
onClick={() => {
toggleExperiment(name);
}}
isPrimary
>
Toggle
</Button>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
}
export default compose(
withSelect((select) => {
const { getExperiments } = select(STORE_KEY);
return {
experiments: getExperiments(),
};
}),
withDispatch((dispatch) => {
const { toggleExperiment } = dispatch(STORE_KEY);
return {
toggleExperiment,
};
})
)(Experiments);

View File

@ -51,8 +51,8 @@
float: right; float: right;
} }
#wc-admin-test-helper-tools { #wc-admin-test-helper-tools, #wc-admin-test-helper-experiments {
table.tools { table.tools, table.experiments {
thead th { thead th {
text-align: center; text-align: center;
} }