department-of-veterans-affairs/vets-website

View on GitHub
src/platform/utilities/feature-toggles/index.jsx

Summary

Maintainability
A
0 mins
Test Coverage
// import React, { useState, useEffect } from 'react';
import {
  TOGGLE_VALUES_SET,
  FETCH_TOGGLE_VALUES_STARTED,
  FETCH_TOGGLE_VALUES_SUCCEEDED,
} from '../../site-wide/feature-toggles/actionTypes';
import environments from '../environment';

import FlipperClient from './flipper-client';
import { useFeatureToggle } from './useFeatureToggle';
import { Toggler } from './Toggler';

const { fetchToggleValues } = FlipperClient({ host: environments.API_URL });

function makeEnvironmentToggleValues(env = environments) {
  return {
    develop: env.isDev(),
    localhost: env.isLocalhost(),
    notProduction: !env.isProduction(),
    staging: env.isStaging(),
    production: env.isProduction(),
  };
}

// TODO: add helper to that gets loading state of feature toggles

const initialToggleValues = {
  ...makeEnvironmentToggleValues(),
};

let updateFeatureToggleValuesFunc = () => {};

// for use only in tests
const updateFeatureToggleValue = newToggleValues =>
  updateFeatureToggleValuesFunc(newToggleValues);

async function connectFeatureToggle(
  dispatch,
  toggleValues = initialToggleValues,
) {
  // create toggle overriding function for tests
  updateFeatureToggleValuesFunc = newToggleValues =>
    dispatch({
      type: TOGGLE_VALUES_SET,
      newToggleValues,
    });

  // set state with default toggle values
  dispatch({
    type: FETCH_TOGGLE_VALUES_STARTED,
    payload: toggleValues,
  });

  // fetch toggle values from service and update state
  const newToggleValues = await fetchToggleValues();

  dispatch({
    type: FETCH_TOGGLE_VALUES_SUCCEEDED,
    payload: newToggleValues,
  });
}

// TODO: remove or refactor
/*
addSubscriberCallback(newToggleValues => {
  currentToggleValues = {
    ...currentToggleValues,
    ...newToggleValues,
  };
});

const subscribeToToggleUpdates = callback => addSubscriberCallback(callback);

const ToggleContext = React.createContext();

function ToggleProvider(props) {
  const {
    children,
    providerInitialToggleValues,
    subscribeToUpdateToggles = () => {},
    unsubscribeToUpdateToggles = () => {},
  } = props;

  const [toggleValues, setToggleValues] = useState(providerInitialToggleValues);

  useEffect(
    () => {
      function handleToggleValuesUpdate(newToggleValues) {
        setToggleValues({
          ...toggleValues,
          ...newToggleValues,
        });
      }

      subscribeToUpdateToggles(handleToggleValuesUpdate);

      return () => unsubscribeToUpdateToggles();
    },
    [
      providerInitialToggleValues,
      subscribeToUpdateToggles,
      toggleValues,
      unsubscribeToUpdateToggles,
    ],
  );

  return (
    <ToggleContext.Provider value={toggleValues}>
      {children}
    </ToggleContext.Provider>
  );
}

const withFeatureToggleProvider = (
  WrappedComponent,
  toggleValues = initialToggleValues,
  subscribeToUpdateToggles = addSubscriberCallback,
) => props => (
  <ToggleProvider
    providerInitialToggleValues={toggleValues}
    subscribeToUpdateToggles={subscribeToUpdateToggles}
  >
    <WrappedComponent {...props} />
  </ToggleProvider>
);

const FeatureToggle = ({ children, ...props }) => {
  const toggles = Object.keys(props);

  return (
    <ToggleContext.Consumer>
      {toggleValues => {
        const showChildren = toggles.find(toggle => {
          if (!toggleValues) {
            // eslint-disable-next-line no-console
            console.warn(
              `ToggleContext has no values. Make sure the ToggleContext was properly initialized.`,
            );
            return false;
          }

          if (!(toggle in toggleValues)) {
            // eslint-disable-next-line no-console
            console.warn(
              `${toggle} toggle not found. Check that toggle name is correct. All toggle keys must be on the ToggleContext.`,
            );
            return false;
          }
          return toggleValues[toggle];
        });
        return showChildren ? children : null;
      }}
    </ToggleContext.Consumer>
  );
};
*/

export {
  connectFeatureToggle,
  updateFeatureToggleValue,
  // FeatureToggle,
  // subscribeToToggleUpdates,
  // withFeatureToggleProvider,
  useFeatureToggle,
  Toggler,
};