refactor: migrate to common eslint+prettier configs (#4168)

* refactor: migrate to common eslint+prettier configs

* fix: prettier frontend

* feat: config changes

* fix: lint issues

* fix: lint

* fix: type imports

* fix: cyclical import issue

* fix: lockfile

* fix: missing dep

* fix: switch to tabs

* fix: continue switch to tabs

* fix: rustfmt parity

* fix: moderation lint issue

* fix: lint issues

* fix: ui intl

* fix: lint issues

* Revert "fix: rustfmt parity"

This reverts commit cb99d2376c321d813d4b7fc7e2a213bb30a54711.

* feat: revert last rs
This commit is contained in:
Cal H.
2025-08-14 21:48:38 +01:00
committed by GitHub
parent 82697278dc
commit 2aabcf36ee
702 changed files with 101360 additions and 102020 deletions

View File

@@ -1,90 +1,91 @@
<script setup lang="ts" generic="T">
import type { RouteLocationRaw } from 'vue-router'
import AutoLink from '../base/AutoLink.vue'
import Avatar from '../base/Avatar.vue'
import Checkbox from '../base/Checkbox.vue'
import type { RouteLocationRaw } from 'vue-router'
export interface ContentCreator {
name: string
type: 'user' | 'organization'
id: string
link?: string | RouteLocationRaw
// eslint-disable-next-line @typescript-eslint/no-explicit-any
linkProps?: any
name: string
type: 'user' | 'organization'
id: string
link?: string | RouteLocationRaw
// eslint-disable-next-line @typescript-eslint/no-explicit-any
linkProps?: any
}
export interface ContentProject {
id: string
link?: string | RouteLocationRaw
// eslint-disable-next-line @typescript-eslint/no-explicit-any
linkProps?: any
id: string
link?: string | RouteLocationRaw
// eslint-disable-next-line @typescript-eslint/no-explicit-any
linkProps?: any
}
export interface ContentItem<T> {
path: string
disabled: boolean
filename: string
data: T
path: string
disabled: boolean
filename: string
data: T
icon?: string
title?: string
project?: ContentProject
creator?: ContentCreator
icon?: string
title?: string
project?: ContentProject
creator?: ContentCreator
version?: string
versionId?: string
version?: string
versionId?: string
}
withDefaults(
defineProps<{
item: ContentItem<T>
last?: boolean
}>(),
{
last: false,
},
defineProps<{
item: ContentItem<T>
last?: boolean
}>(),
{
last: false,
},
)
const model = defineModel<boolean>()
</script>
<template>
<div
class="grid grid-cols-[min-content,4fr,3fr,2fr] gap-3 items-center p-2 h-[64px] border-solid border-0 border-b-button-bg relative"
:class="{ 'border-b-[1px]': !last }"
>
<Checkbox v-model="model" :description="``" class="select-checkbox" />
<div
class="flex items-center gap-2 text-contrast font-medium"
:class="{ 'opacity-50': item.disabled }"
>
<AutoLink :to="item.project?.link ?? ''" tabindex="-1" v-bind="item.project?.linkProps ?? {}">
<Avatar :src="item.icon ?? ''" :class="{ grayscale: item.disabled }" size="48px" />
</AutoLink>
<div class="flex flex-col">
<AutoLink :to="item.project?.link ?? ''" v-bind="item.project?.linkProps ?? {}">
<div class="text-contrast line-clamp-1" :class="{ 'line-through': item.disabled }">
{{ item.title ?? item.filename }}
</div>
</AutoLink>
<AutoLink :to="item.creator?.link ?? ''" v-bind="item.creator?.linkProps ?? {}">
<div class="line-clamp-1 break-all" :class="{ 'opacity-50': item.disabled }">
<slot v-if="item.creator && item.creator.name" :item="item">
<span class="text-secondary"> by {{ item.creator.name }} </span>
</slot>
</div>
</AutoLink>
</div>
</div>
<div class="flex flex-col max-w-60" :class="{ 'opacity-50': item.disabled }">
<div v-if="item.version" class="line-clamp-1 break-all">
<slot :creator="item.creator">
{{ item.version }}
</slot>
</div>
<div class="text-secondary text-xs line-clamp-1 break-all">{{ item.filename }}</div>
</div>
<div class="flex justify-end gap-1 items-center">
<slot name="actions" :item="item" />
</div>
</div>
<div
class="grid grid-cols-[min-content,4fr,3fr,2fr] gap-3 items-center p-2 h-[64px] border-solid border-0 border-b-button-bg relative"
:class="{ 'border-b-[1px]': !last }"
>
<Checkbox v-model="model" :description="``" class="select-checkbox" />
<div
class="flex items-center gap-2 text-contrast font-medium"
:class="{ 'opacity-50': item.disabled }"
>
<AutoLink :to="item.project?.link ?? ''" tabindex="-1" v-bind="item.project?.linkProps ?? {}">
<Avatar :src="item.icon ?? ''" :class="{ grayscale: item.disabled }" size="48px" />
</AutoLink>
<div class="flex flex-col">
<AutoLink :to="item.project?.link ?? ''" v-bind="item.project?.linkProps ?? {}">
<div class="text-contrast line-clamp-1" :class="{ 'line-through': item.disabled }">
{{ item.title ?? item.filename }}
</div>
</AutoLink>
<AutoLink :to="item.creator?.link ?? ''" v-bind="item.creator?.linkProps ?? {}">
<div class="line-clamp-1 break-all" :class="{ 'opacity-50': item.disabled }">
<slot v-if="item.creator && item.creator.name" :item="item">
<span class="text-secondary"> by {{ item.creator.name }} </span>
</slot>
</div>
</AutoLink>
</div>
</div>
<div class="flex flex-col max-w-60" :class="{ 'opacity-50': item.disabled }">
<div v-if="item.version" class="line-clamp-1 break-all">
<slot :creator="item.creator">
{{ item.version }}
</slot>
</div>
<div class="text-secondary text-xs line-clamp-1 break-all">{{ item.filename }}</div>
</div>
<div class="flex justify-end gap-1 items-center">
<slot name="actions" :item="item" />
</div>
</div>
</template>

View File

@@ -1,27 +1,28 @@
<script setup lang="ts" generic="T">
import { ref, computed } from 'vue'
import type { Ref } from 'vue'
import Checkbox from '../base/Checkbox.vue'
import ContentListItem from './ContentListItem.vue'
import type { ContentItem } from './ContentListItem.vue'
import { DropdownIcon } from '@modrinth/assets'
import type { Ref } from 'vue'
import { computed, ref } from 'vue'
import Checkbox from '../base/Checkbox.vue'
import type { ContentItem } from './ContentListItem.vue'
import ContentListItem from './ContentListItem.vue'
const props = withDefaults(
defineProps<{
items: ContentItem<T>[]
sortColumn: string
sortAscending: boolean
updateSort: (column: string) => void
currentPage: number
}>(),
{},
defineProps<{
items: ContentItem<T>[]
sortColumn: string
sortAscending: boolean
updateSort: (column: string) => void
currentPage: number
}>(),
{},
)
const selectionStates: Ref<Record<string, boolean>> = ref({})
const selected: Ref<string[]> = computed(() =>
Object.keys(selectionStates.value).filter(
(item) => selectionStates.value[item] && props.items.some((x) => x.filename === item),
),
Object.keys(selectionStates.value).filter(
(item) => selectionStates.value[item] && props.items.some((x) => x.filename === item),
),
)
const allSelected = ref(false)
@@ -29,70 +30,70 @@ const allSelected = ref(false)
const model = defineModel<string[]>()
function updateSelection() {
model.value = selected.value
model.value = selected.value
}
function setSelected(value: boolean) {
if (value) {
selectionStates.value = Object.fromEntries(props.items.map((item) => [item.filename, true]))
} else {
selectionStates.value = {}
}
updateSelection()
if (value) {
selectionStates.value = Object.fromEntries(props.items.map((item) => [item.filename, true]))
} else {
selectionStates.value = {}
}
updateSelection()
}
const paginatedItems = computed(() =>
props.items.slice((props.currentPage - 1) * 20, props.currentPage * 20),
props.items.slice((props.currentPage - 1) * 20, props.currentPage * 20),
)
</script>
<template>
<div class="flex flex-col grid-cols-[min-content,auto,auto,auto,auto]">
<div
:class="`${$slots.headers ? 'flex' : 'grid'} grid-cols-[min-content,4fr,3fr,2fr] gap-3 items-center px-2 pt-1 h-10 mb-3 text-contrast font-bold`"
>
<Checkbox
v-model="allSelected"
class="select-checkbox"
:indeterminate="selected.length > 0 && selected.length < items.length"
@update:model-value="setSelected"
/>
<slot name="headers">
<div class="flex items-center gap-2 cursor-pointer" @click="updateSort('Name')">
Name
<DropdownIcon
v-if="sortColumn === 'Name'"
class="transition-all transform"
:class="{ 'rotate-180': sortAscending }"
/>
</div>
<div class="flex items-center gap-1 max-w-60 cursor-pointer" @click="updateSort('Updated')">
Updated
<DropdownIcon
v-if="sortColumn === 'Updated'"
class="transition-all transform"
:class="{ 'rotate-180': sortAscending }"
/>
</div>
<div class="flex justify-end gap-2">
<slot name="header-actions" />
</div>
</slot>
</div>
<div class="bg-bg-raised rounded-xl">
<ContentListItem
v-for="(itemRef, index) in paginatedItems"
:key="itemRef.filename"
v-model="selectionStates[itemRef.filename]"
:item="itemRef"
:last="index === paginatedItems.length - 1"
class="mb-2"
@update:model-value="updateSelection"
>
<template #actions="{ item }">
<slot name="actions" :item="item" />
</template>
</ContentListItem>
</div>
</div>
<div class="flex flex-col grid-cols-[min-content,auto,auto,auto,auto]">
<div
:class="`${$slots.headers ? 'flex' : 'grid'} grid-cols-[min-content,4fr,3fr,2fr] gap-3 items-center px-2 pt-1 h-10 mb-3 text-contrast font-bold`"
>
<Checkbox
v-model="allSelected"
class="select-checkbox"
:indeterminate="selected.length > 0 && selected.length < items.length"
@update:model-value="setSelected"
/>
<slot name="headers">
<div class="flex items-center gap-2 cursor-pointer" @click="updateSort('Name')">
Name
<DropdownIcon
v-if="sortColumn === 'Name'"
class="transition-all transform"
:class="{ 'rotate-180': sortAscending }"
/>
</div>
<div class="flex items-center gap-1 max-w-60 cursor-pointer" @click="updateSort('Updated')">
Updated
<DropdownIcon
v-if="sortColumn === 'Updated'"
class="transition-all transform"
:class="{ 'rotate-180': sortAscending }"
/>
</div>
<div class="flex justify-end gap-2">
<slot name="header-actions" />
</div>
</slot>
</div>
<div class="bg-bg-raised rounded-xl">
<ContentListItem
v-for="(itemRef, index) in paginatedItems"
:key="itemRef.filename"
v-model="selectionStates[itemRef.filename]"
:item="itemRef"
:last="index === paginatedItems.length - 1"
class="mb-2"
@update:model-value="updateSelection"
>
<template #actions="{ item }">
<slot name="actions" :item="item" />
</template>
</ContentListItem>
</div>
</div>
</template>

View File

@@ -1,41 +1,42 @@
<script setup lang="ts">
import dayjs from 'dayjs'
import AutoLink from '../base/AutoLink.vue'
export interface Article {
path: string
thumbnail: string
title: string
summary: string
date: string
path: string
thumbnail: string
title: string
summary: string
date: string
}
defineProps<{
article: Article
article: Article
}>()
</script>
<template>
<AutoLink
:to="article.path"
class="active:scale-[0.99]! group flex flex-col transition-all ease-in-out hover:brightness-125 cursor-pointer"
>
<article class="flex h-full grow flex-col gap-4">
<img
:src="article.thumbnail"
class="aspect-video w-full rounded-xl border-[1px] border-solid border-button-border object-cover"
/>
<div class="flex grow flex-col gap-2">
<h3 class="m-0 text-base leading-tight group-hover:underline">
{{ article.title }}
</h3>
<p v-if="article.summary" class="m-0 text-sm leading-tight text-primary">
{{ article.summary }}
</p>
<div class="mt-auto text-sm text-secondary">
{{ dayjs(article.date).format('MMMM D, YYYY') }}
</div>
</div>
</article>
</AutoLink>
<AutoLink
:to="article.path"
class="active:scale-[0.99]! group flex flex-col transition-all ease-in-out hover:brightness-125 cursor-pointer"
>
<article class="flex h-full grow flex-col gap-4">
<img
:src="article.thumbnail"
class="aspect-video w-full rounded-xl border-[1px] border-solid border-button-border object-cover"
/>
<div class="flex grow flex-col gap-2">
<h3 class="m-0 text-base leading-tight group-hover:underline">
{{ article.title }}
</h3>
<p v-if="article.summary" class="m-0 text-sm leading-tight text-primary">
{{ article.summary }}
</p>
<div class="mt-auto text-sm text-secondary">
{{ dayjs(article.date).format('MMMM D, YYYY') }}
</div>
</div>
</article>
</AutoLink>
</template>