mirror of
https://github.com/modrinth/code.git
synced 2026-07-31 13:16:38 +00:00
fix: small breakdowns fixes (#6473)
* fix: members to member, no dependents to none * feat: add fuzzy search to multiselect options search and projects dropdown * fix: duplicate key
This commit is contained in:
@@ -86,7 +86,7 @@ export const analyticsMessages = defineMessages({
|
||||
},
|
||||
noDependent: {
|
||||
id: 'analytics.value.no-dependent',
|
||||
defaultMessage: 'No dependents',
|
||||
defaultMessage: 'None',
|
||||
},
|
||||
noDependentTooltip: {
|
||||
id: 'analytics.value.no-dependent-tooltip',
|
||||
@@ -370,7 +370,7 @@ export const analyticsBreakdownMessages = defineMessages({
|
||||
},
|
||||
members: {
|
||||
id: 'analytics.breakdown.members',
|
||||
defaultMessage: 'Members',
|
||||
defaultMessage: 'Member',
|
||||
},
|
||||
dependentProjectDownload: {
|
||||
id: 'analytics.breakdown.dependent-project-download',
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
:placeholder="formatMessage(analyticsMessages.selectProjects)"
|
||||
:no-options-message="noProjectsMessage"
|
||||
:searchable="projectOptions.length > 6"
|
||||
fuzzy-search
|
||||
:max-tag-rows="1"
|
||||
:trigger-class="analyticsQueryChipTriggerClass"
|
||||
fit-content
|
||||
@@ -211,6 +212,7 @@
|
||||
:placeholder="formatMessage(analyticsMessages.selectProjects)"
|
||||
:no-options-message="noProjectsMessage"
|
||||
:searchable="projectOptions.length > 6"
|
||||
fuzzy-search
|
||||
:max-tag-rows="1"
|
||||
checkbox-position="right"
|
||||
show-selection-actions
|
||||
@@ -545,7 +547,7 @@ function getProjectOption(
|
||||
return {
|
||||
value: project.id,
|
||||
label: project.name,
|
||||
searchTerms: groupTitle ? [groupTitle] : undefined,
|
||||
searchTerms: [project.id, groupTitle].filter((term): term is string => Boolean(term)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
"message": "Loader"
|
||||
},
|
||||
"analytics.breakdown.members": {
|
||||
"message": "Members"
|
||||
"message": "Member"
|
||||
},
|
||||
"analytics.breakdown.monetization": {
|
||||
"message": "Monetization"
|
||||
@@ -504,7 +504,7 @@
|
||||
"message": "Monetized"
|
||||
},
|
||||
"analytics.value.no-dependent": {
|
||||
"message": "No dependents"
|
||||
"message": "None"
|
||||
},
|
||||
"analytics.value.no-dependent-tooltip": {
|
||||
"message": "Downloaded for reasons other than being a dependency"
|
||||
|
||||
@@ -400,6 +400,7 @@ import 'overlayscrollbars/overlayscrollbars.css'
|
||||
import { CheckIcon, ChevronLeftIcon, MinusIcon, SearchIcon, XIcon } from '@modrinth/assets'
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
import { Menu } from 'floating-vue'
|
||||
import Fuse from 'fuse.js'
|
||||
import { OverlayScrollbars, type PartialOptions } from 'overlayscrollbars'
|
||||
import {
|
||||
type Component,
|
||||
@@ -500,6 +501,7 @@ const props = withDefaults(
|
||||
noOptionsMessage?: string
|
||||
noResultsMessage?: string
|
||||
disableSearchFilter?: boolean
|
||||
fuzzySearch?: boolean
|
||||
includeSelectAllOption?: boolean
|
||||
selectAllLabel?: string
|
||||
showSelectionActions?: boolean
|
||||
@@ -519,6 +521,7 @@ const props = withDefaults(
|
||||
noOptionsMessage: 'No options available',
|
||||
noResultsMessage: 'No results found',
|
||||
includeSelectAllOption: false,
|
||||
fuzzySearch: false,
|
||||
selectAllLabel: 'Select all',
|
||||
showSelectionActions: false,
|
||||
selectionActionsClearLabel: 'Clear',
|
||||
@@ -605,12 +608,32 @@ const popperOverflowTags = shallowRef<MultiSelectOption<T>[]>([])
|
||||
|
||||
const lastClickedValue = shallowRef<{ value: T } | null>(null)
|
||||
|
||||
const fuzzySearchOptions = computed(() =>
|
||||
selectableOptions.value.map((option) => ({
|
||||
option,
|
||||
label: option.label,
|
||||
searchTerms: option.searchTerms ?? [],
|
||||
})),
|
||||
)
|
||||
|
||||
const fuzzyMatcher = computed(
|
||||
() =>
|
||||
new Fuse(fuzzySearchOptions.value, {
|
||||
keys: ['label', 'searchTerms'],
|
||||
threshold: 0.4,
|
||||
ignoreLocation: true,
|
||||
}),
|
||||
)
|
||||
|
||||
const filteredOptions = computed(() => {
|
||||
if (!searchQuery.value || !props.searchable || props.disableSearchFilter) {
|
||||
return props.options
|
||||
}
|
||||
|
||||
const query = searchQuery.value.toLowerCase()
|
||||
const fuzzyMatches = props.fuzzySearch
|
||||
? new Set(fuzzyMatcher.value.search(searchQuery.value).map(({ item }) => item.option))
|
||||
: null
|
||||
const items: MultiSelectItem<T>[] = []
|
||||
let pendingSectionHeader: MultiSelectSectionHeader | null = null
|
||||
|
||||
@@ -620,9 +643,10 @@ const filteredOptions = computed(() => {
|
||||
continue
|
||||
}
|
||||
|
||||
const matches =
|
||||
opt.label.toLowerCase().includes(query) ||
|
||||
opt.searchTerms?.some((term) => term.toLowerCase().includes(query))
|
||||
const matches = fuzzyMatches
|
||||
? fuzzyMatches.has(opt)
|
||||
: opt.label.toLowerCase().includes(query) ||
|
||||
opt.searchTerms?.some((term) => term.toLowerCase().includes(query))
|
||||
|
||||
if (!matches) {
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user