Skip to content

Commit

Permalink
feat(flags): Add C# language examples for feature flags (#28702)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
2 people authored and HamedMP committed Feb 19, 2025
1 parent cbb21ec commit 0a56257
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 1 deletion.
Binary file modified frontend/__snapshots__/lemon-ui-icons--shelf-c--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/lemon-ui-icons--shelf-c--light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions frontend/src/lib/components/CodeSnippet/CodeSnippet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { copyToClipboard } from 'lib/utils/copyToClipboard'
import { useEffect, useState } from 'react'
import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter'
import bash from 'react-syntax-highlighter/dist/esm/languages/prism/bash'
import csharp from 'react-syntax-highlighter/dist/esm/languages/prism/csharp'
import dart from 'react-syntax-highlighter/dist/esm/languages/prism/dart'
import elixir from 'react-syntax-highlighter/dist/esm/languages/prism/elixir'
import go from 'react-syntax-highlighter/dist/esm/languages/prism/go'
Expand Down Expand Up @@ -52,12 +53,15 @@ export enum Language {
Markup = 'markup',
SQL = 'sql',
Kotlin = 'kotlin',
CSharp = 'csharp',
}

export const getLanguage = (lang: string): Language => {
switch (lang) {
case 'bash':
return Language.Bash
case 'csharp':
return Language.CSharp
case 'jsx':
return Language.JSX
case 'javascript':
Expand Down Expand Up @@ -113,6 +117,7 @@ SyntaxHighlighter.registerLanguage(Language.PHP, php)
SyntaxHighlighter.registerLanguage(Language.Python, python)
SyntaxHighlighter.registerLanguage(Language.Dart, dart)
SyntaxHighlighter.registerLanguage(Language.Go, go)
SyntaxHighlighter.registerLanguage(Language.CSharp, csharp)
SyntaxHighlighter.registerLanguage(Language.JSON, json)
SyntaxHighlighter.registerLanguage(Language.YAML, yaml)
SyntaxHighlighter.registerLanguage(Language.HTML, markup)
Expand Down
20 changes: 20 additions & 0 deletions frontend/src/lib/lemon-ui/icons/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,26 @@ export function IconPython(props: LemonIconProps): JSX.Element {
)
}

export function IconCSharp(props: LemonIconProps): JSX.Element {
return (
<LemonIconBase viewBox="0 0 128 128" {...props}>
<path
fill="currentColor"
fillOpacity="0.7"
d="M115.4 30.7L67.1 2.9c-.8-.5-1.9-.7-3.1-.7-1.2 0-2.3.3-3.1.7l-48 27.9c-1.7 1-2.9 3.5-2.9 5.4v55.7c0 1.1.2 2.4 1 3.5l106.8-62c-.6-1.2-1.5-2.1-2.4-2.7z"
/>
<path
fill="currentColor"
d="M10.7 95.3c.5.8 1.2 1.5 1.9 1.9l48.2 27.9c.8.5 1.9.7 3.1.7 1.2 0 2.3-.3 3.1-.7l48-27.9c1.7-1 2.9-3.5 2.9-5.4V36.1c0-.9-.1-1.9-.6-2.8l-106.6 62z"
/>
<path
fill="#fff"
d="M85.3 76.1C81.1 83.5 73.1 88.5 64 88.5c-13.5 0-24.5-11-24.5-24.5s11-24.5 24.5-24.5c9.1 0 17.1 5 21.3 12.5l13-7.5c-6.8-11.9-19.6-20-34.3-20-21.8 0-39.5 17.7-39.5 39.5s17.7 39.5 39.5 39.5c14.6 0 27.4-8 34.2-19.8l-12.9-7.6zM97 66.2l.9-4.3h-4.2v-4.7h5.1L100 51h4.9l-1.2 6.1h3.8l1.2-6.1h4.8l-1.2 6.1h2.4v4.7h-3.3l-.9 4.3h4.2v4.7h-5.1l-1.2 6h-4.9l1.2-6h-3.8l-1.2 6h-4.8l1.2-6h-2.4v-4.7H97zm4.8 0h3.8l.9-4.3h-3.8l-.9 4.3z"
/>
</LemonIconBase>
)
}

export function IconHandClick(props: LemonIconProps): JSX.Element {
return (
<LemonIconBase viewBox="0 0 18 18" {...props}>
Expand Down
21 changes: 20 additions & 1 deletion frontend/src/scenes/feature-flags/FeatureFlagCodeOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IconServer } from '@posthog/icons'
import {
IconAndroidOS,
IconAppleIOS,
IconCSharp,
IconFlutter,
IconGolang,
IconJavascript,
Expand All @@ -17,6 +18,7 @@ import { SDKKey } from '~/types'
import {
AndroidSnippet,
APISnippet,
CSharpSnippet,
FeatureFlagSnippet,
FlutterSnippet,
GolangSnippet,
Expand Down Expand Up @@ -149,9 +151,24 @@ export const OPTIONS: InstructionOption[] = [
key: SDKKey.RUBY,
Icon: IconRuby,
},
{
value: 'C#/.NET',
documentationLink: `${DOC_BASE_URL}libraries/dotnet${UTM_TAGS}`,
Snippet: CSharpSnippet,
type: LibraryType.Server,
key: SDKKey.DOTNET,
Icon: IconCSharp,
},
]

export const LOCAL_EVALUATION_LIBRARIES: string[] = [SDKKey.NODE_JS, SDKKey.PYTHON, SDKKey.RUBY, SDKKey.PHP, SDKKey.GO]
export const LOCAL_EVALUATION_LIBRARIES: string[] = [
SDKKey.NODE_JS,
SDKKey.PYTHON,
SDKKey.RUBY,
SDKKey.PHP,
SDKKey.GO,
SDKKey.DOTNET,
]

export const PAYLOAD_LIBRARIES: string[] = [
SDKKey.API,
Expand All @@ -164,6 +181,7 @@ export const PAYLOAD_LIBRARIES: string[] = [
SDKKey.REACT_NATIVE,
SDKKey.IOS,
SDKKey.FLUTTER,
SDKKey.DOTNET,
SDKKey.GO,
]

Expand All @@ -173,6 +191,7 @@ export const REMOTE_CONFIGURATION_LIBRARIES: string[] = [
SDKKey.PYTHON,
SDKKey.GO,
SDKKey.RUBY,
SDKKey.DOTNET,
]

export const BOOTSTRAPPING_OPTIONS: InstructionOption[] = [
Expand Down
95 changes: 95 additions & 0 deletions frontend/src/scenes/feature-flags/FeatureFlagSnippets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,101 @@ if ${conditional}:
)
}

export function CSharpSnippet({
flagKey,
groupType,
multivariant,
localEvaluation,
payload,
remoteConfiguration,
encryptedPayload,
samplePropertyName,
}: FeatureFlagSnippet): JSX.Element {
const clientSuffix = 'posthog.'
const flagFunction = payload
? 'GetFeatureFlagAsync'
: multivariant
? 'GetFeatureFlagAsync'
: 'IsFeatureEnabledAsync'

const propertyName = samplePropertyName || 'isAuthorized'

if (remoteConfiguration) {
const reminder = `// ` + REMOTE_CONFIG_REMINDER + (encryptedPayload ? `\n// ${ENCRYPTED_PAYLOAD_REMINDER}` : '')

return (
<>
<CodeSnippet language={Language.CSharp} wrap>
{`${reminder}
var remoteConfigPayload = await posthog.GetRemoteConfigPayloadAsync("${flagKey}");`}
</CodeSnippet>
</>
)
}

const localEvalCommentAddition = localEvaluation
? groupType
? `// add group properties used in the flag to ensure the flag
// is evaluated locally, vs. going to our servers
`
: `// add person properties used in the flag to ensure the flag
// is evaluated locally, vs. going to our servers
`
: ''

const localEvalCodeAddition = localEvaluation
? groupType
? `{ ["${propertyName}"] = "value", ["name"] = "xyz" }`
: `
personProperties: new() { ["${propertyName}"] = "value" }`
: ''

const flagSnippet = groupType
? `await ${clientSuffix}${flagFunction}(
"${flagKey}",
"user distinct id",
new FeatureFlagOptions
{
${localEvalCommentAddition}Groups = [new Group("${groupType.group_type}", "<${
groupType.name_singular || 'group'
} ID>")${localEvalCodeAddition}]
}
);`
: localEvalCodeAddition
? `await ${clientSuffix}${flagFunction}(
"${flagKey}",
"user distinct id",${localEvalCodeAddition}
);`
: `await ${clientSuffix}${flagFunction}("${flagKey}", "user distinct id");`
const variableName = payload ? 'matchedFlagPayload' : multivariant ? 'enabledVariant' : 'isMyFlagEnabled'

const conditional = multivariant ? `${variableName} == 'example-variant'` : `${variableName}`

const followUpCode = payload
? `
if (matchedFlagPayload is { Payload: {} payload })
{
// The payload is a JsonDocument.
Console.WriteLine(payload.RootElement.GetRawText());
}`
: `
if (${conditional}) {
// Do something differently for this ${groupType ? groupType.name_singular || 'group' : 'user'}
}
`

return (
<>
<CodeSnippet language={Language.CSharp} wrap>
{`${
localEvaluation ? '// ' + LOCAL_EVAL_REMINDER : ''
}var ${variableName} = ${flagSnippet}${followUpCode}`}
</CodeSnippet>
</>
)
}

export function AndroidSnippet({ flagKey, multivariant, payload }: FeatureFlagSnippet): JSX.Element {
const clientSuffix = 'PostHog.'

Expand Down
1 change: 1 addition & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4482,6 +4482,7 @@ export enum SDKKey {
BUBBLE = 'bubble',
DJANGO = 'django',
DOCUSAURUS = 'docusaurus',
DOTNET = 'dotnet',
ELIXIR = 'elixir',
FRAMER = 'framer',
FLUTTER = 'flutter',
Expand Down

0 comments on commit 0a56257

Please sign in to comment.