feat(editor): Show template credential setup based on feature flag (#7989)

Replace the local storage based feature flag with posthog feature flag.

Also:
- Fix bunch of eslint warnings in posthog store
This commit is contained in:
Tomi Turtiainen
2023-12-11 20:21:10 +02:00
committed by GitHub
parent c378f60a25
commit 08ee307209
9 changed files with 89 additions and 87 deletions

View File

@@ -617,7 +617,9 @@ export const ASK_AI_EXPERIMENT = {
gpt4: 'gpt4',
};
export const EXPERIMENTS_TO_TRACK = [ASK_AI_EXPERIMENT.name];
export const TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT = '016_template_credential_setup';
export const EXPERIMENTS_TO_TRACK = [ASK_AI_EXPERIMENT.name, TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT];
export const MFA_AUTHENTICATION_REQUIRED_ERROR_CODE = 998;

View File

@@ -14,6 +14,8 @@ const EVENTS = {
IS_PART_OF_EXPERIMENT: 'User is part of experiment',
};
export type PosthogStore = ReturnType<typeof usePostHog>;
export const usePostHog = defineStore('posthog', () => {
const usersStore = useUsersStore();
const settingsStore = useSettingsStore();
@@ -39,6 +41,13 @@ export const usePostHog = defineStore('posthog', () => {
return getVariant(experiment) === variant;
};
/**
* Checks if the given feature flag is enabled. Should only be used for boolean flags
*/
const isFeatureEnabled = (experiment: keyof FeatureFlags) => {
return featureFlags.value?.[experiment] === true;
};
if (!window.featureFlags) {
// for testing
const cachedOverrides = useStorage(LOCAL_STORAGE_EXPERIMENT_OVERRIDES).value;
@@ -65,7 +74,7 @@ export const usePostHog = defineStore('posthog', () => {
},
getVariant,
getAll: () => featureFlags.value || {},
getAll: () => featureFlags.value ?? {},
};
}
@@ -90,6 +99,25 @@ export const usePostHog = defineStore('posthog', () => {
};
};
const trackExperiment = (featFlags: FeatureFlags, name: string) => {
const variant = featFlags[name];
if (!variant || trackedDemoExp.value[name] === variant) {
return;
}
telemetryStore.track(EVENTS.IS_PART_OF_EXPERIMENT, {
name,
variant,
});
trackedDemoExp.value[name] = variant;
};
const trackExperiments = (featFlags: FeatureFlags) => {
EXPERIMENTS_TO_TRACK.forEach((name) => trackExperiment(featFlags, name));
};
const trackExperimentsDebounced = debounce(trackExperiments, 2000);
const init = (evaluatedFeatureFlags?: FeatureFlags) => {
if (!window.posthog) {
return;
@@ -143,25 +171,6 @@ export const usePostHog = defineStore('posthog', () => {
}
};
const trackExperiments = (featureFlags: FeatureFlags) => {
EXPERIMENTS_TO_TRACK.forEach((name) => trackExperiment(featureFlags, name));
};
const trackExperimentsDebounced = debounce(trackExperiments, 2000);
const trackExperiment = (featureFlags: FeatureFlags, name: string) => {
const variant = featureFlags[name];
if (!variant || trackedDemoExp.value[name] === variant) {
return;
}
telemetryStore.track(EVENTS.IS_PART_OF_EXPERIMENT, {
name,
variant,
});
trackedDemoExp.value[name] = variant;
};
const capture = (event: string, properties: IDataObject) => {
if (typeof window.posthog?.capture === 'function') {
window.posthog.capture(event, properties);
@@ -181,6 +190,7 @@ export const usePostHog = defineStore('posthog', () => {
return {
init,
isFeatureEnabled,
isVariantEnabled,
getVariant,
reset,

View File

@@ -1,16 +0,0 @@
// Feature flags
export const enum FeatureFlag {
templateCredentialsSetup = 'template-credentials-setup',
}
const hasLocaleStorageKey = (key: string): boolean => {
try {
// Local storage might not be available in all envs e.g. when user has
// disabled it in their browser
return !!localStorage.getItem(key);
} catch (e) {
return false;
}
};
export const isFeatureFlagEnabled = (flag: FeatureFlag): boolean => hasLocaleStorageKey(flag);

View File

@@ -1,9 +1,9 @@
import type { INodeUi, IWorkflowData, IWorkflowTemplate } from '@/Interface';
import { getNewWorkflow } from '@/api/workflows';
import { VIEWS } from '@/constants';
import { TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT, VIEWS } from '@/constants';
import type { useRootStore } from '@/stores/n8nRoot.store';
import type { PosthogStore } from '@/stores/posthog.store';
import type { useWorkflowsStore } from '@/stores/workflows.store';
import { FeatureFlag, isFeatureFlagEnabled } from '@/utils/featureFlag';
import { getFixedNodesList } from '@/utils/nodeViewUtils';
import type { TemplateCredentialKey } from '@/utils/templates/templateTransforms';
import { replaceAllTemplateNodeCredentials } from '@/utils/templates/templateTransforms';
@@ -45,13 +45,16 @@ export async function createWorkflowFromTemplate(
* if the feature flag is disabled)
*/
export async function openTemplateCredentialSetup(opts: {
posthogStore: PosthogStore;
templateId: string;
router: Router;
inNewBrowserTab?: boolean;
}) {
const { router, templateId, inNewBrowserTab = false } = opts;
const { router, templateId, inNewBrowserTab = false, posthogStore } = opts;
const routeLocation: RouteLocationRaw = isFeatureFlagEnabled(FeatureFlag.templateCredentialsSetup)
const routeLocation: RouteLocationRaw = posthogStore.isFeatureEnabled(
TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT,
)
? {
name: VIEWS.TEMPLATE_SETUP,
params: { id: templateId },

View File

@@ -66,10 +66,9 @@ import type {
} from '@/Interface';
import { setPageTitle } from '@/utils/htmlUtils';
import { VIEWS } from '@/constants';
import { TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT, VIEWS } from '@/constants';
import { useTemplatesStore } from '@/stores/templates.store';
import { usePostHog } from '@/stores/posthog.store';
import { FeatureFlag, isFeatureFlagEnabled } from '@/utils/featureFlag';
import { openTemplateCredentialSetup } from '@/utils/templates/templateActions';
import { useExternalHooks } from '@/composables/useExternalHooks';
@@ -129,7 +128,7 @@ export default defineComponent({
this.navigateTo(event, VIEWS.TEMPLATE, id);
},
async onUseWorkflow({ event, id }: { event: MouseEvent; id: string }) {
if (!isFeatureFlagEnabled(FeatureFlag.templateCredentialsSetup)) {
if (this.posthogStore.isFeatureEnabled(TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT)) {
const telemetryPayload = {
template_id: id,
wf_template_repo_session_id: this.templatesStore.currentSessionId,
@@ -142,6 +141,7 @@ export default defineComponent({
}
await openTemplateCredentialSetup({
posthogStore: this.posthogStore,
router: this.$router,
templateId: id,
inNewBrowserTab: event.metaKey || event.ctrlKey,

View File

@@ -69,8 +69,8 @@ import { setPageTitle } from '@/utils/htmlUtils';
import { useTemplatesStore } from '@/stores/templates.store';
import { usePostHog } from '@/stores/posthog.store';
import { openTemplateCredentialSetup } from '@/utils/templates/templateActions';
import { FeatureFlag, isFeatureFlagEnabled } from '@/utils/featureFlag';
import { useExternalHooks } from '@/composables/useExternalHooks';
import { TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT } from '@/constants';
export default defineComponent({
name: 'TemplatesWorkflowView',
@@ -107,7 +107,7 @@ export default defineComponent({
},
methods: {
async openTemplateSetup(id: string, e: PointerEvent) {
if (!isFeatureFlagEnabled(FeatureFlag.templateCredentialsSetup)) {
if (!this.posthogStore.isFeatureEnabled(TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT)) {
const telemetryPayload = {
source: 'workflow',
template_id: id,
@@ -121,6 +121,7 @@ export default defineComponent({
}
await openTemplateCredentialSetup({
posthogStore: this.posthogStore,
router: this.$router,
templateId: id,
inNewBrowserTab: e.metaKey || e.ctrlKey,