summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/feature_flags/store/helpers.js
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-21 07:08:36 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-21 07:08:36 +0000
commit48aff82709769b098321c738f3444b9bdaa694c6 (patch)
treee00c7c43e2d9b603a5a6af576b1685e400410dee /app/assets/javascripts/feature_flags/store/helpers.js
parent879f5329ee916a948223f8f43d77fba4da6cd028 (diff)
downloadgitlab-ce-48aff82709769b098321c738f3444b9bdaa694c6.tar.gz
Add latest changes from gitlab-org/gitlab@13-5-stable-eev13.5.0-rc42
Diffstat (limited to 'app/assets/javascripts/feature_flags/store/helpers.js')
-rw-r--r--app/assets/javascripts/feature_flags/store/helpers.js213
1 files changed, 213 insertions, 0 deletions
diff --git a/app/assets/javascripts/feature_flags/store/helpers.js b/app/assets/javascripts/feature_flags/store/helpers.js
new file mode 100644
index 00000000000..db6da815abf
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/helpers.js
@@ -0,0 +1,213 @@
+import { isEmpty, uniqueId, isString } from 'lodash';
+import {
+ ROLLOUT_STRATEGY_ALL_USERS,
+ ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
+ ROLLOUT_STRATEGY_USER_ID,
+ ROLLOUT_STRATEGY_GITLAB_USER_LIST,
+ INTERNAL_ID_PREFIX,
+ DEFAULT_PERCENT_ROLLOUT,
+ PERCENT_ROLLOUT_GROUP_ID,
+ fetchPercentageParams,
+ fetchUserIdParams,
+ LEGACY_FLAG,
+} from '../constants';
+
+/**
+ * Converts raw scope objects fetched from the API into an array of scope
+ * objects that is easier/nicer to bind to in Vue.
+ * @param {Array} scopesFromRails An array of scope objects fetched from the API
+ */
+export const mapToScopesViewModel = scopesFromRails =>
+ (scopesFromRails || []).map(s => {
+ const percentStrategy = (s.strategies || []).find(
+ strat => strat.name === ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
+ );
+
+ const rolloutPercentage = fetchPercentageParams(percentStrategy) || DEFAULT_PERCENT_ROLLOUT;
+
+ const userStrategy = (s.strategies || []).find(
+ strat => strat.name === ROLLOUT_STRATEGY_USER_ID,
+ );
+
+ const rolloutStrategy =
+ (percentStrategy && percentStrategy.name) ||
+ (userStrategy && userStrategy.name) ||
+ ROLLOUT_STRATEGY_ALL_USERS;
+
+ const rolloutUserIds = (fetchUserIdParams(userStrategy) || '')
+ .split(',')
+ .filter(id => id)
+ .join(', ');
+
+ return {
+ id: s.id,
+ environmentScope: s.environment_scope,
+ active: Boolean(s.active),
+ canUpdate: Boolean(s.can_update),
+ protected: Boolean(s.protected),
+ rolloutStrategy,
+ rolloutPercentage,
+ rolloutUserIds,
+
+ // eslint-disable-next-line no-underscore-dangle
+ shouldBeDestroyed: Boolean(s._destroy),
+ shouldIncludeUserIds: rolloutUserIds.length > 0 && percentStrategy !== null,
+ };
+ });
+/**
+ * Converts the parameters emitted by the Vue component into
+ * the shape that the Rails API expects.
+ * @param {Array} scopesFromVue An array of scope objects from the Vue component
+ */
+export const mapFromScopesViewModel = params => {
+ const scopes = (params.scopes || []).map(s => {
+ const parameters = {};
+ if (s.rolloutStrategy === ROLLOUT_STRATEGY_PERCENT_ROLLOUT) {
+ parameters.groupId = PERCENT_ROLLOUT_GROUP_ID;
+ parameters.percentage = s.rolloutPercentage;
+ } else if (s.rolloutStrategy === ROLLOUT_STRATEGY_USER_ID) {
+ parameters.userIds = (s.rolloutUserIds || '').replace(/, /g, ',');
+ }
+
+ const userIdParameters = {};
+
+ if (s.shouldIncludeUserIds && s.rolloutStrategy !== ROLLOUT_STRATEGY_USER_ID) {
+ userIdParameters.userIds = (s.rolloutUserIds || '').replace(/, /g, ',');
+ }
+
+ // Strip out any internal IDs
+ const id = isString(s.id) && s.id.startsWith(INTERNAL_ID_PREFIX) ? undefined : s.id;
+
+ const strategies = [
+ {
+ name: s.rolloutStrategy,
+ parameters,
+ },
+ ];
+
+ if (!isEmpty(userIdParameters)) {
+ strategies.push({ name: ROLLOUT_STRATEGY_USER_ID, parameters: userIdParameters });
+ }
+
+ return {
+ id,
+ environment_scope: s.environmentScope,
+ active: s.active,
+ can_update: s.canUpdate,
+ protected: s.protected,
+ _destroy: s.shouldBeDestroyed,
+ strategies,
+ };
+ });
+
+ const model = {
+ operations_feature_flag: {
+ name: params.name,
+ description: params.description,
+ active: params.active,
+ scopes_attributes: scopes,
+ version: LEGACY_FLAG,
+ },
+ };
+
+ return model;
+};
+
+/**
+ * Creates a new feature flag environment scope object for use
+ * in a Vue component. An optional parameter can be passed to
+ * override the property values that are created by default.
+ *
+ * @param {Object} overrides An optional object whose
+ * property values will be used to override the default values.
+ *
+ */
+export const createNewEnvironmentScope = (overrides = {}, featureFlagPermissions = false) => {
+ const defaultScope = {
+ environmentScope: '',
+ active: false,
+ id: uniqueId(INTERNAL_ID_PREFIX),
+ rolloutStrategy: ROLLOUT_STRATEGY_ALL_USERS,
+ rolloutPercentage: DEFAULT_PERCENT_ROLLOUT,
+ rolloutUserIds: '',
+ };
+
+ const newScope = {
+ ...defaultScope,
+ ...overrides,
+ };
+
+ if (featureFlagPermissions) {
+ newScope.canUpdate = true;
+ newScope.protected = false;
+ }
+
+ return newScope;
+};
+
+const mapStrategyScopesToRails = scopes =>
+ scopes.length === 0
+ ? [{ environment_scope: '*' }]
+ : scopes.map(s => ({
+ id: s.id,
+ _destroy: s.shouldBeDestroyed,
+ environment_scope: s.environmentScope,
+ }));
+
+const mapStrategyScopesToView = scopes =>
+ scopes.map(s => ({
+ id: s.id,
+ // eslint-disable-next-line no-underscore-dangle
+ shouldBeDestroyed: Boolean(s._destroy),
+ environmentScope: s.environment_scope,
+ }));
+
+const mapStrategiesParametersToViewModel = params => {
+ if (params.userIds) {
+ return { ...params, userIds: params.userIds.split(',').join(', ') };
+ }
+ return params;
+};
+
+export const mapStrategiesToViewModel = strategiesFromRails =>
+ (strategiesFromRails || []).map(s => ({
+ id: s.id,
+ name: s.name,
+ parameters: mapStrategiesParametersToViewModel(s.parameters),
+ userListId: s.user_list?.id,
+ // eslint-disable-next-line no-underscore-dangle
+ shouldBeDestroyed: Boolean(s._destroy),
+ scopes: mapStrategyScopesToView(s.scopes),
+ }));
+
+const mapStrategiesParametersToRails = params => {
+ if (params.userIds) {
+ return { ...params, userIds: params.userIds.replace(/\s*,\s*/g, ',') };
+ }
+ return params;
+};
+
+const mapStrategyToRails = strategy => {
+ const mappedStrategy = {
+ id: strategy.id,
+ name: strategy.name,
+ _destroy: strategy.shouldBeDestroyed,
+ scopes_attributes: mapStrategyScopesToRails(strategy.scopes || []),
+ parameters: mapStrategiesParametersToRails(strategy.parameters),
+ };
+
+ if (strategy.name === ROLLOUT_STRATEGY_GITLAB_USER_LIST) {
+ mappedStrategy.user_list_id = strategy.userListId;
+ }
+ return mappedStrategy;
+};
+
+export const mapStrategiesToRails = params => ({
+ operations_feature_flag: {
+ name: params.name,
+ description: params.description,
+ version: params.version,
+ active: params.active,
+ strategies_attributes: (params.strategies || []).map(mapStrategyToRails),
+ },
+});