-
Notifications
You must be signed in to change notification settings - Fork 4
ENG-1191: add new setting component for feature flag #633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: eng-1188-create-a-pull-watch-handler-on-the-settings-page-per-feature
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import { getFeatureFlag, setFeatureFlag } from "~/utils/manageFeatureFlag"; | ||
| import { type FeatureFlags } from "~/utils/zodSchemaForSettings"; | ||
| import { Checkbox } from "@blueprintjs/core"; | ||
| import Description from "roamjs-components/components/Description"; | ||
| import idToTitle from "roamjs-components/util/idToTitle"; | ||
| import React, { useState } from "react"; | ||
|
|
||
| export const BlockPropFeatureFlagPanel = ({ | ||
| title, | ||
| description, | ||
| featureKey, | ||
| }: { | ||
| title: string; | ||
| description: string; | ||
| featureKey: keyof FeatureFlags; | ||
| }) => { | ||
| const [value, setValue] = useState(() => getFeatureFlag(featureKey)); | ||
|
|
||
| const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
| const { checked } = e.target; | ||
| setFeatureFlag(featureKey, checked); | ||
| setValue(checked); | ||
| }; | ||
|
|
||
| return ( | ||
| <Checkbox | ||
| checked={value} | ||
| onChange={handleChange} | ||
| labelElement={ | ||
| <> | ||
| {idToTitle(title)} | ||
| <Description description={description} /> | ||
| </> | ||
| } | ||
| /> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,27 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| import { FeatureFlagsSchema, type FeatureFlags } from "./zodSchemaForSettings"; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { TOP_LEVEL_BLOCK_PROP_KEYS } from "~/data/blockPropsSettingsConfig"; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||
| setBlockPropBasedSettings, | ||||||||||||||||||||||||||||||||||||||||||||||
| getBlockPropBasedSettings, | ||||||||||||||||||||||||||||||||||||||||||||||
| } from "~/utils/settingsUsingBlockProps"; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export const getFeatureFlag = (key: keyof FeatureFlags): boolean => { | ||||||||||||||||||||||||||||||||||||||||||||||
| const featureFlagKey = TOP_LEVEL_BLOCK_PROP_KEYS.featureFlags; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const { blockProps } = getBlockPropBasedSettings({ | ||||||||||||||||||||||||||||||||||||||||||||||
| keys: [featureFlagKey], | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const flags = FeatureFlagsSchema.parse(blockProps || {}); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| return flags[key]; | ||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+9
to
+19
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Since Once feature flags are added to the schema, consider adding a fallback default value to handle cases where a flag isn't yet defined: 🔎 Suggested improvement for robustness export const getFeatureFlag = (key: keyof FeatureFlags): boolean => {
const featureFlagKey = TOP_LEVEL_BLOCK_PROP_KEYS.featureFlags;
const { blockProps } = getBlockPropBasedSettings({
keys: [featureFlagKey],
});
const flags = FeatureFlagsSchema.parse(blockProps || {});
- return flags[key];
+ return flags[key] ?? false; // Default to false if key is missing
};This ensures the function always returns a boolean even if a flag isn't explicitly set in storage. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export const setFeatureFlag = ( | ||||||||||||||||||||||||||||||||||||||||||||||
| key: keyof FeatureFlags, | ||||||||||||||||||||||||||||||||||||||||||||||
| value: boolean, | ||||||||||||||||||||||||||||||||||||||||||||||
| ): void => { | ||||||||||||||||||||||||||||||||||||||||||||||
| const featureFlagKey = TOP_LEVEL_BLOCK_PROP_KEYS.featureFlags; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| void setBlockPropBasedSettings({ keys: [featureFlagKey, key], value }); | ||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,8 @@ | ||||||||||||||||||
| import { z } from "zod"; | ||||||||||||||||||
|
|
||||||||||||||||||
| /* eslint-disable @typescript-eslint/naming-convention */ | ||||||||||||||||||
| export const FeatureFlagsSchema = z.object({ | ||||||||||||||||||
| }); | ||||||||||||||||||
|
Comment on lines
+4
to
+5
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find apps/roam -type f -name "*zodSchemaForSettings*" 2>/dev/nullRepository: DiscourseGraphs/discourse-graph Length of output: 118 🏁 Script executed: cat -n apps/roam/src/utils/zodSchemaForSettings.tsRepository: DiscourseGraphs/discourse-graph Length of output: 385 🏁 Script executed: rg -n "FeatureFlagsSchema|getFeatureFlag|setFeatureFlag|BlockPropFeatureFlagPanel" apps/roam/src --type ts --type tsxRepository: DiscourseGraphs/discourse-graph Length of output: 102 🏁 Script executed: rg -n "FeatureFlag" apps/roam/src -A 3 -B 1 --type ts --type tsxRepository: DiscourseGraphs/discourse-graph Length of output: 102 🏁 Script executed: rg -n "zodSchemaForSettings" apps/roam/src --type ts --type tsxRepository: DiscourseGraphs/discourse-graph Length of output: 102 🏁 Script executed: rg -n "import.*FeatureFlagsSchema|from.*zodSchemaForSettings" apps/roam/src --type ts --type tsxRepository: DiscourseGraphs/discourse-graph Length of output: 102 🏁 Script executed: find apps/roam/src -type f \( -name "*.ts" -o -name "*.tsx" \) -exec grep -l "feature\|flag" {} \; 2>/dev/nullRepository: DiscourseGraphs/discourse-graph Length of output: 568 🏁 Script executed: cd apps/roam/src/utils && git log --oneline -n 20 zodSchemaForSettings.ts 2>/dev/null || echo "No git history available"Repository: DiscourseGraphs/discourse-graph Length of output: 125 🏁 Script executed: head -20 apps/roam/src/utils/zodSchemaForSettings.tsRepository: DiscourseGraphs/discourse-graph Length of output: 329 🏁 Script executed: rg -n "TODO|FIXME|feature.flag|TODO.*feature" apps/roam/src --type ts --type tsx -i | head -20Repository: DiscourseGraphs/discourse-graph Length of output: 102 🏁 Script executed: cat -n apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsxRepository: DiscourseGraphs/discourse-graph Length of output: 1329 🏁 Script executed: cat -n apps/roam/src/utils/isFlagEnabled.tsRepository: DiscourseGraphs/discourse-graph Length of output: 874 🏁 Script executed: cat -n apps/roam/src/utils/manageFeatureFlag.tsRepository: DiscourseGraphs/discourse-graph Length of output: 1073 🏁 Script executed: cat -n apps/roam/src/utils/pullWatchBlockPropsBasedSettings.ts | head -50Repository: DiscourseGraphs/discourse-graph Length of output: 720 🏁 Script executed: cat -n apps/roam/src/data/blockPropsSettingsConfig.tsRepository: DiscourseGraphs/discourse-graph Length of output: 259 Add at least one feature flag definition to make the type system functional.
Add at least one flag definition: export const FeatureFlagsSchema = z.object({
+ exampleFeature: z.boolean().default(false),
});Alternatively, document in a comment that this PR establishes foundational infrastructure with flag definitions to be added in follow-up PRs. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| /* eslint-disable @typescript-eslint/naming-convention */ | ||||||||||||||||||
|
Comment on lines
+3
to
+6
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the ESLint comment pairing. Line 6 duplicates the 🔎 Proposed fix /* eslint-disable @typescript-eslint/naming-convention */
export const FeatureFlagsSchema = z.object({
});
-/* eslint-disable @typescript-eslint/naming-convention */
+/* eslint-enable @typescript-eslint/naming-convention */📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| export type FeatureFlags = z.infer<typeof FeatureFlagsSchema>; | ||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add explicit return type annotation.
Per coding guidelines, functions should have explicit return types. Add
: React.JSX.Elementor: JSX.Elementto the component signature.🔎 Proposed fix
export const BlockPropFeatureFlagPanel = ({ title, description, featureKey, }: { title: string; description: string; featureKey: keyof FeatureFlags; -}) => { +}): React.JSX.Element => {As per coding guidelines, "Use explicit return types for functions."
📝 Committable suggestion
🤖 Prompt for AI Agents