refactor: move flags into settings, change icon (#5678)
* refactor: move flags into settings, change icon * fix: use ButtonStyled for app
This commit is contained in:
@@ -1,78 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { SearchIcon } from '@modrinth/assets'
|
||||
import { 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[])
|
||||
|
||||
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="mx-auto my-4 box-border w-[calc(100%-2rem)] max-w-[800px]">
|
||||
<h1 class="mb-4 text-2xl font-bold text-contrast">Feature flags</h1>
|
||||
<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>
|
||||
<Toggle
|
||||
:id="`toggle-${flag}`"
|
||||
v-model="flags[flag]"
|
||||
@update:model-value="() => saveFeatureFlags()"
|
||||
/>
|
||||
</div>
|
||||
<p v-if="filteredFlags.length === 0" class="text-center text-secondary">
|
||||
No flags found matching "{{ searchQuery }}"
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -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
|
||||
? {
|
||||
@@ -91,6 +98,7 @@ import {
|
||||
PaintbrushIcon,
|
||||
ServerIcon,
|
||||
ShieldIcon,
|
||||
ToggleRightIcon,
|
||||
UserIcon,
|
||||
} from '@modrinth/assets'
|
||||
import { commonMessages, commonSettingsMessages, defineMessages, useVIntl } from '@modrinth/ui'
|
||||
@@ -116,6 +124,7 @@ const messages = defineMessages({
|
||||
|
||||
const route = useNativeRoute()
|
||||
const auth = await useAuth()
|
||||
const flags = useFeatureFlags()
|
||||
|
||||
useSeoMeta({
|
||||
robots: 'noindex',
|
||||
|
||||
87
apps/frontend/src/pages/settings/flags.vue
Normal file
87
apps/frontend/src/pages/settings/flags.vue
Normal file
@@ -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>
|
||||
Reference in New Issue
Block a user