Skip to content

Commit

Permalink
Add feature flags (#578)
Browse files Browse the repository at this point in the history
* Add feature flags

* chore: remove setdefaultflags

* fix: checked on admin debug page

* make enabled toggle råsa

* fix: remove need to use onMount for feature flags

---------

Co-authored-by: Alfred Grip <[email protected]>
  • Loading branch information
Isak-Kallini and alfredgrip authored Nov 26, 2024
1 parent 07d5dec commit 5456f64
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 45 deletions.
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default defineConfig({
{ text: "Setting up VS Code", link: "/guides/vscode" },
{ text: "Next steps", link: "/guides/next-steps" },
{ text: "Load testing", link: "/guides/load-testing" },
{ text: "Using feature flags", link: "/guides/featureflags" },
],
},
{
Expand Down
24 changes: 24 additions & 0 deletions docs/guides/featureflags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Feature flags

When working on larger features we want to avoid long lived branches with a lot of changes. This can be avoided by hiding the feature behind a feature flag.

1. Add your flag to the array `featureFlags` in `src/lib/utils/featureFlag.ts`.

2. Go to the relevant component/page and add

```typescript
import { isFeatureFlagEnabled } from "$lib/utils/featureFlag";
let isEnabled = isFeatureFlagEnabled("newFeature");
```

3. Go to `/admin/debug` to toggle the feature flag

4. Use

```svelte
{#if isEnabled}
Awesome new feature goes here
{/if}
```

in the relevant component/page to hide your feature until it's ready.
22 changes: 22 additions & 0 deletions src/lib/utils/featureFlag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { browser } from "$app/environment";

export const featureFlags: string[] = [];

export const isFeatureFlagEnabled = (flag: string) => {
if (!featureFlags.includes(flag) || !browser) {
return false;
}
const value = localStorage.getItem(flag);
if (value === null || value === "false") {
return false;
}
return true;
};

export const setFeatureFlag = (flag: string, value: boolean) => {
if (!featureFlags.includes(flag)) {
return false;
}
localStorage.setItem(flag, value.toString());
return true;
};
130 changes: 85 additions & 45 deletions src/routes/(app)/admin/debug/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,96 @@
import { version } from "$app/environment";
import { page } from "$app/stores";
import { isAuthorized } from "$lib/utils/authorization";
import {
featureFlags,
isFeatureFlagEnabled,
setFeatureFlag,
} from "$lib/utils/featureFlag";
import { onMount } from "svelte";
export let data;
$: user = data.user;
$: policies = user.policies.toSorted();
$: flags = new Map<string, boolean>();
onMount(() => {
const flagMap = new Map<string, boolean>();
featureFlags.forEach((f) => {
flagMap.set(f, isFeatureFlagEnabled(f));
flags = flagMap;
});
});
</script>

{#if isAuthorized("core:admin", $page.data.user)}
<section class="mb-4">
<h1 class="mb-2 text-lg font-semibold">Actions</h1>
<form action="?/keycloakSync" method="POST" class="flex items-center gap-4">
<button type="submit" class="btn">Sync with Keycloak</button>
<p>This will push mandates and pull email addresses.</p>
</form>
</section>
{/if}
<div class="flex flex-row gap-10">
<div>
{#if isAuthorized("core:admin", $page.data.user)}
<section class="mb-4">
<h1 class="mb-2 text-lg font-semibold">Actions</h1>
<form
action="?/keycloakSync"
method="POST"
class="flex items-center gap-4"
>
<button type="submit" class="btn">Sync with Keycloak</button>
<p>This will push mandates and pull email addresses.</p>
</form>
</section>
{/if}

<section>
<h1 class="text-lg font-semibold">Metadata</h1>
<ul class="ml-4 list-disc">
<li>
Version:
<pre class="inline">{version}</pre>
<span
class="badge badge-neutral tooltip tooltip-bottom aspect-square px-1"
data-tip="This is guaranteed to match the version of the code that is running and is retrieved at build-time. It optionally suffixes the tag name with the number of additional commits on top of the tagged commit (i.e -2) and the abbreviated hash of the most recent commit (i.e -g<hash>)."
>
?
</span>
</li>
<li>
Prisma log level:
<pre class="inline">{data.prismaLogLevel}</pre>
</li>
<li>Is nollning: {data.isNollning}</li>
<li>
Is app: {data.isApp}
</li>
<li>
App info: {JSON.stringify(data.appInfo)}
</li>
</ul>
</section>
<section>
<h1 class="text-lg font-semibold">Metadata</h1>
<ul class="ml-4 list-disc">
<li>
Version:
<pre class="inline">{version}</pre>
<span
class="badge badge-neutral tooltip tooltip-bottom aspect-square px-1"
data-tip="This is guaranteed to match the version of the code that is running and is retrieved at build-time. It optionally suffixes the tag name with the number of additional commits on top of the tagged commit (i.e -2) and the abbreviated hash of the most recent commit (i.e -g<hash>)."
>
?
</span>
</li>
<li>
Prisma log level:
<pre class="inline">{data.prismaLogLevel}</pre>
</li>
<li>Is nollning: {data.isNollning}</li>
<li>
Is app: {data.isApp}
</li>
<li>
App info: {JSON.stringify(data.appInfo)}
</li>
</ul>
</section>

<section class="mt-4">
<h1 class="text-lg font-semibold">
User: {user.studentId ?? user.externalCode}
</h1>
<ul class="ml-4 list-disc text-sm">
{#each policies as permission}
<li>{permission}</li>
{/each}
</ul>
</section>
<section class="mt-4">
<h1 class="text-lg font-semibold">
User: {user.studentId ?? user.externalCode}
</h1>
<ul class="ml-4 list-disc text-sm">
{#each policies as permission}
<li>{permission}</li>
{/each}
</ul>
</section>
</div>
<div>
<section>
<h1 class="text-lg font-semibold">Feature flags</h1>
{#each featureFlags as flag}
<div class="flex gap-5">
{flag}
<input
type="checkbox"
class="toggle toggle-primary"
checked={flags.get(flag)}
on:change={() => {
setFeatureFlag(flag, isFeatureFlagEnabled(flag) ? false : true);
}}
/>
</div>
{/each}
</section>
</div>
</div>

0 comments on commit 5456f64

Please sign in to comment.