Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import {
LanguagesIcon,
ModrinthIcon,
PaintbrushIcon,
ReportIcon,
SettingsIcon,
ShieldIcon,
ToggleRightIcon,
} from '@modrinth/assets'
import {
commonMessages,
commonSettingsMessages,
defineMessage,
defineMessages,
ProgressBar,
Expand Down Expand Up @@ -95,11 +96,8 @@ const tabs = [
content: ResourceManagementSettings,
},
{
name: defineMessage({
id: 'app.settings.tabs.feature-flags',
defaultMessage: 'Feature flags',
}),
icon: ReportIcon,
name: commonSettingsMessages.featureFlags,
icon: ToggleRightIcon,
content: FeatureFlagSettings,
developerOnly: true,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { Toggle } from '@modrinth/ui'
import { ButtonStyled, Toggle } from '@modrinth/ui'
import { ref, watch } from 'vue'

import { get as getSettings, set as setSettings } from '@/helpers/settings.ts'
Expand Down Expand Up @@ -31,11 +31,20 @@ watch(
{{ option.replaceAll('_', ' ') }}
</h2>
</div>

<Toggle
id="advanced-rendering"
:model-value="themeStore.getFeatureFlag(option)"
@update:model-value="() => setFeatureFlag(option, !themeStore.getFeatureFlag(option))"
/>
<div class="flex items-center gap-2">
<ButtonStyled type="transparent">
<button
:disabled="themeStore.getFeatureFlag(option) === DEFAULT_FEATURE_FLAGS[option]"
@click="setFeatureFlag(option, DEFAULT_FEATURE_FLAGS[option])"
>
Reset to default
</button>
</ButtonStyled>
<Toggle
id="advanced-rendering"
:model-value="themeStore.getFeatureFlag(option)"
@update:model-value="() => setFeatureFlag(option, !themeStore.getFeatureFlag(option))"
/>
</div>
</div>
</template>
3 changes: 0 additions & 3 deletions apps/app-frontend/src/locales/en-US/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Default instance options"
},
"app.settings.tabs.feature-flags": {
"message": "Feature flags"
},
"app.settings.tabs.java-installations": {
"message": "Java installations"
},
Expand Down
17 changes: 8 additions & 9 deletions apps/frontend/src/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,8 @@
<SettingsIcon aria-hidden="true" /> {{ formatMessage(commonMessages.settingsLabel) }}
</template>
<template #flags>
<ReportIcon aria-hidden="true" /> {{ formatMessage(messages.featureFlags) }}
<ToggleRightIcon aria-hidden="true" />
{{ formatMessage(commonSettingsMessages.featureFlags) }}
</template>
<template #projects>
<BoxIcon aria-hidden="true" /> {{ formatMessage(messages.projects) }}
Expand Down Expand Up @@ -585,9 +586,9 @@
<ScaleIcon aria-hidden="true" />
{{ formatMessage(commonMessages.moderationLabel) }}
</NuxtLink>
<NuxtLink v-if="flags.developerMode" class="iconified-button" to="/flags">
<ReportIcon aria-hidden="true" />
{{ formatMessage(messages.featureFlags) }}
<NuxtLink v-if="flags.developerMode" class="iconified-button" to="/settings/flags">
<ToggleRightIcon aria-hidden="true" />
{{ formatMessage(commonSettingsMessages.featureFlags) }}
</NuxtLink>
</template>
<NuxtLink class="iconified-button" to="/settings">
Expand Down Expand Up @@ -724,6 +725,7 @@ import {
SettingsIcon,
ShieldAlertIcon,
SunIcon,
ToggleRightIcon,
TransferIcon,
UserIcon,
UserSearchIcon,
Expand All @@ -734,6 +736,7 @@ import {
ButtonStyled,
commonMessages,
commonProjectTypeCategoryMessages,
commonSettingsMessages,
defineMessages,
injectModrinthClient,
OverflowMenu,
Expand Down Expand Up @@ -918,10 +921,6 @@ const messages = defineMessages({
id: 'layout.nav.upgrade-to-modrinth-plus',
defaultMessage: 'Upgrade to Modrinth+',
},
featureFlags: {
id: 'layout.nav.feature-flags',
defaultMessage: 'Feature flags',
},
projects: {
id: 'layout.nav.projects',
defaultMessage: 'Projects',
Expand Down Expand Up @@ -1045,7 +1044,7 @@ const userMenuOptions = computed(() => {
},
{
id: 'flags',
link: '/flags',
link: '/settings/flags',
shown: flags.value.developerMode,
},
{
Expand Down
3 changes: 0 additions & 3 deletions apps/frontend/src/locales/en-US/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -1709,9 +1709,6 @@
"layout.nav.discover-content": {
"message": "Discover content"
},
"layout.nav.feature-flags": {
"message": "Feature flags"
},
"layout.nav.get-modrinth-app": {
"message": "Get Modrinth App"
},
Expand Down
6 changes: 6 additions & 0 deletions apps/frontend/src/middleware/flags-redirect.global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default defineNuxtRouteMiddleware((to) => {
if (to.path.startsWith('/flags')) {
const target = to.fullPath.replace('/flags', '/settings/flags')
return navigateTo(target, { redirectCode: 301 })
}
})
78 changes: 0 additions & 78 deletions apps/frontend/src/pages/flags.vue

This file was deleted.

9 changes: 9 additions & 0 deletions apps/frontend/src/pages/settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
icon: LanguagesIcon,
badge: `${formatMessage(commonMessages.beta)}`,
},
flags.developerMode
? {
link: '/settings/flags',
label: formatMessage(commonSettingsMessages.featureFlags),
icon: ToggleRightIcon,
}
: null,
auth.user ? { type: 'heading', label: formatMessage(messages.account) } : null,
auth.user
? {
Expand Down Expand Up @@ -91,6 +98,7 @@ import {
PaintbrushIcon,
ServerIcon,
ShieldIcon,
ToggleRightIcon,
UserIcon,
} from '@modrinth/assets'
import { commonMessages, commonSettingsMessages, defineMessages, useVIntl } from '@modrinth/ui'
Expand All @@ -116,6 +124,7 @@ const messages = defineMessages({

const route = useNativeRoute()
const auth = await useAuth()
const flags = useFeatureFlags()

useSeoMeta({
robots: 'noindex',
Expand Down
87 changes: 87 additions & 0 deletions apps/frontend/src/pages/settings/flags.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<script setup lang="ts">
import { SearchIcon } from '@modrinth/assets'
import { ButtonStyled, StyledInput, Toggle } from '@modrinth/ui'
import Fuse from 'fuse.js'
import { computed, ref, shallowReactive } from 'vue'

import {
DEFAULT_FEATURE_FLAGS,
type FeatureFlag,
saveFeatureFlags,
useFeatureFlags,
} from '~/composables/featureFlags.ts'

const flags = shallowReactive(useFeatureFlags().value)
const searchQuery = ref('')

const allFlags = computed(() => Object.keys(flags) as FeatureFlag[])

function resetFlag(flag: FeatureFlag) {
flags[flag] = DEFAULT_FEATURE_FLAGS[flag]
saveFeatureFlags()
}

const fuse = computed(
() =>
new Fuse(allFlags.value, {
threshold: 0.4,
}),
)

const filteredFlags = computed(() => {
if (!searchQuery.value.trim()) {
return allFlags.value
}
return fuse.value.search(searchQuery.value).map((result) => result.item)
})

useSeoMeta({
robots: 'noindex',
})
</script>

<template>
<div class="mb-2">
<StyledInput
v-model="searchQuery"
type="search"
:icon="SearchIcon"
placeholder="Search flags..."
wrapper-class="w-full rounded-xl bg-bg-raised"
/>
</div>
<div class="flex flex-col gap-2">
<div
v-for="flag in filteredFlags"
:key="`flag-${flag}`"
class="flex flex-row flex-wrap items-center gap-2 rounded-2xl bg-bg-raised p-4"
>
<label :for="`toggle-${flag}`" class="flex-1">
<span class="block font-semibold capitalize">
{{ flag.replaceAll('_', ' ') }}
</span>
<p class="m-0 text-secondary">
Default:
<span :class="DEFAULT_FEATURE_FLAGS[flag] === false ? 'text-red' : 'text-green'">
{{ DEFAULT_FEATURE_FLAGS[flag] }}
</span>
</p>
</label>
<div class="flex items-center gap-2">
<ButtonStyled type="transparent">
<button :disabled="flags[flag] === DEFAULT_FEATURE_FLAGS[flag]" @click="resetFlag(flag)">
Reset to default
</button>
</ButtonStyled>
<Toggle
:id="`toggle-${flag}`"
v-model="flags[flag]"
@update:model-value="() => saveFeatureFlags()"
/>
</div>
</div>
<p v-if="filteredFlags.length === 0" class="text-center text-secondary">
No flags found matching "{{ searchQuery }}"
</p>
</div>
</template>
3 changes: 3 additions & 0 deletions packages/ui/src/locales/en-US/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -2354,6 +2354,9 @@
"settings.display.theme.title": {
"defaultMessage": "Color theme"
},
"settings.feature-flags.title": {
"defaultMessage": "Feature flags"
},
"settings.language.categories.default": {
"defaultMessage": "Standard languages"
},
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/utils/common-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,10 @@ export const commonSettingsMessages = defineMessages({
id: 'settings.billing.title',
defaultMessage: 'Billing and subscriptions',
},
featureFlags: {
id: 'settings.feature-flags.title',
defaultMessage: 'Feature flags',
},
language: {
id: 'settings.language.title',
defaultMessage: 'Language',
Expand Down
Loading