fix: checklist conditional message issues + MD formatting (#3989)

This commit is contained in:
IMB11 2025-07-13 21:23:06 +01:00 committed by GitHub
parent 058185c7fd
commit c1b95ede07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 160 additions and 105 deletions

View File

@ -38,10 +38,10 @@
"@intercom/messenger-js-sdk": "^0.0.14", "@intercom/messenger-js-sdk": "^0.0.14",
"@ltd/j-toml": "^1.38.0", "@ltd/j-toml": "^1.38.0",
"@modrinth/assets": "workspace:*", "@modrinth/assets": "workspace:*",
"@modrinth/ui": "workspace:*",
"@modrinth/utils": "workspace:*",
"@modrinth/blog": "workspace:*", "@modrinth/blog": "workspace:*",
"@modrinth/moderation": "workspace:*", "@modrinth/moderation": "workspace:*",
"@modrinth/ui": "workspace:*",
"@modrinth/utils": "workspace:*",
"@pinia/nuxt": "^0.5.1", "@pinia/nuxt": "^0.5.1",
"@types/three": "^0.172.0", "@types/three": "^0.172.0",
"@vintl/vintl": "^4.4.1", "@vintl/vintl": "^4.4.1",
@ -59,6 +59,7 @@
"markdown-it": "14.1.0", "markdown-it": "14.1.0",
"pathe": "^1.1.2", "pathe": "^1.1.2",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"prettier": "^3.6.2",
"qrcode.vue": "^3.4.0", "qrcode.vue": "^3.4.0",
"semver": "^7.5.4", "semver": "^7.5.4",
"three": "^0.172.0", "three": "^0.172.0",

View File

@ -115,10 +115,12 @@ html {
--shadow-inset-sm: inset 0px -1px 2px hsla(221, 39%, 11%, 0.15); --shadow-inset-sm: inset 0px -1px 2px hsla(221, 39%, 11%, 0.15);
--shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2); --shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2);
--shadow-raised: 0.3px 0.5px 0.6px hsl(var(--shadow-color) / 0.15), --shadow-raised:
0.3px 0.5px 0.6px hsl(var(--shadow-color) / 0.15),
1px 2px 2.2px -1.7px hsl(var(--shadow-color) / 0.12), 1px 2px 2.2px -1.7px hsl(var(--shadow-color) / 0.12),
4.4px 8.8px 9.7px -3.4px hsl(var(--shadow-color) / 0.09); 4.4px 8.8px 9.7px -3.4px hsl(var(--shadow-color) / 0.09);
--shadow-floating: hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, --shadow-floating:
hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, hsla(0, 0%, 0%, 0.1) 0px 2px 4px -1px; hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, hsla(0, 0%, 0%, 0.1) 0px 2px 4px -1px;
--shadow-card: rgba(50, 50, 100, 0.1) 0px 2px 4px 0px; --shadow-card: rgba(50, 50, 100, 0.1) 0px 2px 4px 0px;
@ -150,8 +152,8 @@ html {
rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0.35) 0%,
rgba(255, 255, 255, 0.2695) 100% rgba(255, 255, 255, 0.2695) 100%
); );
--landing-blob-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16), --landing-blob-shadow:
inset 2px 2px 64px rgba(255, 255, 255, 0.45); 2px 2px 12px rgba(0, 0, 0, 0.16), inset 2px 2px 64px rgba(255, 255, 255, 0.45);
--landing-card-bg: rgba(255, 255, 255, 0.8); --landing-card-bg: rgba(255, 255, 255, 0.8);
--landing-card-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16); --landing-card-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16);
@ -251,13 +253,15 @@ html {
--shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2); --shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2);
--shadow-raised: 0px -2px 4px hsla(221, 39%, 11%, 0.1); --shadow-raised: 0px -2px 4px hsla(221, 39%, 11%, 0.1);
--shadow-floating: hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, --shadow-floating:
hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px; hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;
--shadow-card: rgba(0, 0, 0, 0.25) 0px 2px 4px 0px; --shadow-card: rgba(0, 0, 0, 0.25) 0px 2px 4px 0px;
--landing-maze-bg: url("https://cdn.modrinth.com/landing-new/landing.webp"); --landing-maze-bg: url("https://cdn.modrinth.com/landing-new/landing.webp");
--landing-maze-gradient-bg: linear-gradient(0deg, #31375f 0%, rgba(8, 14, 55, 0) 100%), --landing-maze-gradient-bg:
linear-gradient(0deg, #31375f 0%, rgba(8, 14, 55, 0) 100%),
url("https://cdn.modrinth.com/landing-new/landing-lower.webp"); url("https://cdn.modrinth.com/landing-new/landing-lower.webp");
--landing-maze-outer-bg: linear-gradient(180deg, #06060d 0%, #000000 100%); --landing-maze-outer-bg: linear-gradient(180deg, #06060d 0%, #000000 100%);
@ -284,7 +288,8 @@ html {
rgba(44, 48, 79, 0.35) 0%, rgba(44, 48, 79, 0.35) 0%,
rgba(32, 35, 50, 0.2695) 100% rgba(32, 35, 50, 0.2695) 100%
); );
--landing-blob-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16), inset 2px 2px 64px rgba(57, 61, 94, 0.45); --landing-blob-shadow:
2px 2px 12px rgba(0, 0, 0, 0.16), inset 2px 2px 64px rgba(57, 61, 94, 0.45);
--landing-card-bg: rgba(59, 63, 85, 0.15); --landing-card-bg: rgba(59, 63, 85, 0.15);
--landing-card-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16); --landing-card-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16);
@ -360,8 +365,9 @@ body {
// Defaults // Defaults
background-color: var(--color-bg); background-color: var(--color-bg);
color: var(--color-text); color: var(--color-text);
--font-standard: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, --font-standard:
Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, Cantarell,
Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
--mono-font: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; --mono-font: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
font-family: var(--font-standard); font-family: var(--font-standard);
font-size: 16px; font-size: 16px;

View File

@ -382,6 +382,7 @@ import type {
import ModpackPermissionsFlow from "./ModpackPermissionsFlow.vue"; import ModpackPermissionsFlow from "./ModpackPermissionsFlow.vue";
import KeybindsModal from "./ChecklistKeybindsModal.vue"; import KeybindsModal from "./ChecklistKeybindsModal.vue";
import { finalPermissionMessages } from "@modrinth/moderation/data/modpack-permissions-stage"; import { finalPermissionMessages } from "@modrinth/moderation/data/modpack-permissions-stage";
import prettier from "prettier";
const keybindsModal = ref<InstanceType<typeof KeybindsModal>>(); const keybindsModal = ref<InstanceType<typeof KeybindsModal>>();
@ -923,16 +924,28 @@ async function processAction(
conditionalAction.messageVariants, conditionalAction.messageVariants,
selectedActionIds, selectedActionIds,
allValidActionIds, allValidActionIds,
stageIndex,
); );
let message: string;
let weight: number;
if (matchingVariant) { if (matchingVariant) {
const message = (await matchingVariant.message()) as string; message = (await matchingVariant.message()) as string;
weight = matchingVariant.weight;
} else if (conditionalAction.fallbackMessage) {
message = (await conditionalAction.fallbackMessage()) as string;
weight = conditionalAction.fallbackWeight ?? 0;
} else {
return;
}
messageParts.push({ messageParts.push({
weight: matchingVariant.weight, weight,
content: processMessage(message, action, stageIndex, textInputValues.value), content: processMessage(message, action, stageIndex, textInputValues.value),
actionId, actionId,
stageIndex, stageIndex,
}); });
}
} else if (action.type === "dropdown") { } else if (action.type === "dropdown") {
const dropdownAction = action as DropdownAction; const dropdownAction = action as DropdownAction;
const selectedIndex = state.value ?? 0; const selectedIndex = state.value ?? 0;
@ -1077,7 +1090,20 @@ async function generateMessage() {
} }
} }
try {
const formattedMessage = await prettier.format(fullMessage, {
parser: "markdown",
printWidth: 80,
proseWrap: "always",
tabWidth: 2,
useTabs: false,
});
message.value = formattedMessage;
} catch (formattingError) {
console.warn("Failed to format markdown, using original:", formattingError);
message.value = fullMessage; message.value = fullMessage;
}
generatedMessage.value = true; generatedMessage.value = true;
} catch (error) { } catch (error) {
console.error("Error generating message:", error); console.error("Error generating message:", error);

View File

@ -112,7 +112,8 @@ export async function useServersFetch<T>(
const response = await $fetch<T>(fullUrl, { const response = await $fetch<T>(fullUrl, {
method, method,
headers, headers,
body: body && contentType === "application/json" ? JSON.stringify(body) : body ?? undefined, body:
body && contentType === "application/json" ? JSON.stringify(body) : (body ?? undefined),
timeout: 10000, timeout: 10000,
}); });

View File

@ -29,12 +29,11 @@
class="settings-header__icon" class="settings-header__icon"
/> />
<div class="settings-header__text"> <div class="settings-header__text">
<h1 class="wrap-as-needed"> <h1 class="wrap-as-needed">{{ project.title }}</h1>
{{ project.title }}
</h1>
<ProjectStatusBadge :status="project.status" /> <ProjectStatusBadge :status="project.status" />
</div> </div>
</div> </div>
<h2>Project settings</h2> <h2>Project settings</h2>
<NavStack> <NavStack>
<NavStackItem <NavStackItem
@ -111,6 +110,7 @@
</NavStack> </NavStack>
</aside> </aside>
</div> </div>
<div class="normal-page__content"> <div class="normal-page__content">
<ProjectMemberHeader <ProjectMemberHeader
v-if="currentMember" v-if="currentMember"
@ -145,6 +145,7 @@
/> />
</div> </div>
</div> </div>
<div v-else class="experimental-styles-within"> <div v-else class="experimental-styles-within">
<NewModal ref="settingsModal"> <NewModal ref="settingsModal">
<template #title> <template #title>
@ -174,9 +175,11 @@
<div <div
class="animation-ring-3 flex items-center justify-center rounded-full border-4 border-solid border-brand bg-brand-highlight opacity-40" class="animation-ring-3 flex items-center justify-center rounded-full border-4 border-solid border-brand bg-brand-highlight opacity-40"
></div> ></div>
<div <div
class="animation-ring-2 flex items-center justify-center rounded-full border-4 border-solid border-brand bg-brand-highlight opacity-60" class="animation-ring-2 flex items-center justify-center rounded-full border-4 border-solid border-brand bg-brand-highlight opacity-60"
></div> ></div>
<div <div
class="animation-ring-1 flex items-center justify-center rounded-full border-4 border-solid border-brand bg-brand-highlight" class="animation-ring-1 flex items-center justify-center rounded-full border-4 border-solid border-brand bg-brand-highlight"
> >
@ -219,8 +222,7 @@
:href="`modrinth://mod/${project.slug}`" :href="`modrinth://mod/${project.slug}`"
@click="() => installWithApp()" @click="() => installWithApp()"
> >
<ModrinthIcon aria-hidden="true" /> <ModrinthIcon aria-hidden="true" /> Install with Modrinth App
Install with Modrinth App
<ExternalIcon aria-hidden="true" /> <ExternalIcon aria-hidden="true" />
</a> </a>
</ButtonStyled> </ButtonStyled>
@ -240,6 +242,7 @@
<div class="flex h-[2px] w-full rounded-2xl bg-button-bg"></div> <div class="flex h-[2px] w-full rounded-2xl bg-button-bg"></div>
</div> </div>
</div> </div>
<div class="mx-auto flex w-fit flex-col gap-2"> <div class="mx-auto flex w-fit flex-col gap-2">
<ButtonStyled v-if="project.game_versions.length === 1"> <ButtonStyled v-if="project.game_versions.length === 1">
<div class="disabled button-like"> <div class="disabled button-like">
@ -327,8 +330,7 @@
} }
" "
> >
{{ gameVersion }} {{ gameVersion }} <CheckIcon v-if="userSelectedGameVersion === gameVersion" />
<CheckIcon v-if="userSelectedGameVersion === gameVersion" />
</button> </button>
</ButtonStyled> </ButtonStyled>
</ScrollablePanel> </ScrollablePanel>
@ -419,7 +421,6 @@
</ScrollablePanel> </ScrollablePanel>
</Accordion> </Accordion>
</div> </div>
<AutomaticAccordion div class="flex flex-col gap-2"> <AutomaticAccordion div class="flex flex-col gap-2">
<VersionSummary <VersionSummary
v-if="filteredRelease" v-if="filteredRelease"
@ -489,11 +490,11 @@
:color="route.name === 'type-id-version-version' ? `standard` : `brand`" :color="route.name === 'type-id-version-version' ? `standard` : `brand`"
> >
<button @click="(event) => downloadModal.show(event)"> <button @click="(event) => downloadModal.show(event)">
<DownloadIcon aria-hidden="true" /> <DownloadIcon aria-hidden="true" /> Download
Download
</button> </button>
</ButtonStyled> </ButtonStyled>
</div> </div>
<div class="contents sm:hidden"> <div class="contents sm:hidden">
<ButtonStyled <ButtonStyled
size="large" size="large"
@ -558,9 +559,11 @@
</button> </button>
</ButtonStyled> </ButtonStyled>
</div> </div>
<p class="m-0 text-wrap text-sm font-medium leading-tight text-secondary"> <p class="m-0 text-wrap text-sm font-medium leading-tight text-secondary">
Modrinth Servers is the easiest way to play with your friends without hassle! Modrinth Servers is the easiest way to play with your friends without hassle!
</p> </p>
<p class="m-0 text-wrap text-sm font-bold text-primary"> <p class="m-0 text-wrap text-sm font-bold text-primary">
Starting at $5<span class="text-xs"> / month</span> Starting at $5<span class="text-xs"> / month</span>
</p> </p>
@ -625,6 +628,7 @@
{{ option.name }} {{ option.name }}
</Checkbox> </Checkbox>
</div> </div>
<div v-else class="menu-text"> <div v-else class="menu-text">
<p class="popout-text">No collections found.</p> <p class="popout-text">No collections found.</p>
</div> </div>
@ -632,8 +636,7 @@
class="btn collection-button" class="btn collection-button"
@click="(event) => $refs.modal_collection.show(event)" @click="(event) => $refs.modal_collection.show(event)"
> >
<PlusIcon aria-hidden="true" /> <PlusIcon aria-hidden="true" /> Create new collection
Create new collection
</button> </button>
</template> </template>
</PopoutMenu> </PopoutMenu>
@ -716,25 +719,14 @@
:dropdown-id="`${baseId}-more-options`" :dropdown-id="`${baseId}-more-options`"
> >
<MoreVerticalIcon aria-hidden="true" /> <MoreVerticalIcon aria-hidden="true" />
<template #analytics> <template #analytics> <ChartIcon aria-hidden="true" /> Analytics </template>
<ChartIcon aria-hidden="true" />
Analytics
</template>
<template #moderation-checklist> <template #moderation-checklist>
<ScaleIcon aria-hidden="true" /> <ScaleIcon aria-hidden="true" /> Review project
Review project
</template>
<template #report>
<ReportIcon aria-hidden="true" />
Report
</template>
<template #copy-id>
<ClipboardCopyIcon aria-hidden="true" />
Copy ID
</template> </template>
<template #report> <ReportIcon aria-hidden="true" /> Report </template>
<template #copy-id> <ClipboardCopyIcon aria-hidden="true" /> Copy ID </template>
<template #copy-permalink> <template #copy-permalink>
<ClipboardCopyIcon aria-hidden="true" /> <ClipboardCopyIcon aria-hidden="true" /> Copy permanent link
Copy permanent link
</template> </template>
</OverflowMenu> </OverflowMenu>
</ButtonStyled> </ButtonStyled>
@ -760,6 +752,7 @@
updates unless the author decides to unarchive the project. updates unless the author decides to unarchive the project.
</MessageBanner> </MessageBanner>
</div> </div>
<div class="normal-page__sidebar"> <div class="normal-page__sidebar">
<ProjectSidebarCompatibility <ProjectSidebarCompatibility
:project="project" :project="project"
@ -789,6 +782,7 @@
/> />
<div class="card flex-card experimental-styles-within"> <div class="card flex-card experimental-styles-within">
<h2>{{ formatMessage(detailsMessages.title) }}</h2> <h2>{{ formatMessage(detailsMessages.title) }}</h2>
<div class="details-list"> <div class="details-list">
<div class="details-list__item"> <div class="details-list__item">
<BookTextIcon aria-hidden="true" /> <BookTextIcon aria-hidden="true" />
@ -817,53 +811,48 @@
<span v-else>{{ licenseIdDisplay }}</span> <span v-else>{{ licenseIdDisplay }}</span>
</div> </div>
</div> </div>
<div <div
v-if="project.approved" v-if="project.approved"
v-tooltip="$dayjs(project.approved).format('MMMM D, YYYY [at] h:mm A')" v-tooltip="$dayjs(project.approved).format('MMMM D, YYYY [at] h:mm A')"
class="details-list__item" class="details-list__item"
> >
<CalendarIcon aria-hidden="true" /> <CalendarIcon aria-hidden="true" />
<div> <div>{{ formatMessage(detailsMessages.published, { date: publishedDate }) }}</div>
{{ formatMessage(detailsMessages.published, { date: publishedDate }) }}
</div>
</div> </div>
<div <div
v-else v-else
v-tooltip="$dayjs(project.published).format('MMMM D, YYYY [at] h:mm A')" v-tooltip="$dayjs(project.published).format('MMMM D, YYYY [at] h:mm A')"
class="details-list__item" class="details-list__item"
> >
<CalendarIcon aria-hidden="true" /> <CalendarIcon aria-hidden="true" />
<div> <div>{{ formatMessage(detailsMessages.created, { date: createdDate }) }}</div>
{{ formatMessage(detailsMessages.created, { date: createdDate }) }}
</div>
</div> </div>
<div <div
v-if="project.status === 'processing' && project.queued" v-if="project.status === 'processing' && project.queued"
v-tooltip="$dayjs(project.queued).format('MMMM D, YYYY [at] h:mm A')" v-tooltip="$dayjs(project.queued).format('MMMM D, YYYY [at] h:mm A')"
class="details-list__item" class="details-list__item"
> >
<ScaleIcon aria-hidden="true" /> <ScaleIcon aria-hidden="true" />
<div> <div>{{ formatMessage(detailsMessages.submitted, { date: submittedDate }) }}</div>
{{ formatMessage(detailsMessages.submitted, { date: submittedDate }) }}
</div>
</div> </div>
<div <div
v-if="versions.length > 0 && project.updated" v-if="versions.length > 0 && project.updated"
v-tooltip="$dayjs(project.updated).format('MMMM D, YYYY [at] h:mm A')" v-tooltip="$dayjs(project.updated).format('MMMM D, YYYY [at] h:mm A')"
class="details-list__item" class="details-list__item"
> >
<VersionIcon aria-hidden="true" /> <VersionIcon aria-hidden="true" />
<div> <div>{{ formatMessage(detailsMessages.updated, { date: updatedDate }) }}</div>
{{ formatMessage(detailsMessages.updated, { date: updatedDate }) }}
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="normal-page__content"> <div class="normal-page__content">
<div class="overflow-x-auto"> <div class="overflow-x-auto"><NavTabs :links="navLinks" class="mb-4" /></div>
<NavTabs :links="navLinks" class="mb-4" />
</div>
<NuxtPage <NuxtPage
v-model:project="project" v-model:project="project"
v-model:versions="versions" v-model:versions="versions"
@ -881,6 +870,7 @@
@delete-version="deleteVersion" @delete-version="deleteVersion"
/> />
</div> </div>
<div class="normal-page__ultimate-sidebar"> <div class="normal-page__ultimate-sidebar">
<!-- Uncomment this to enable the old moderation checklist. --> <!-- Uncomment this to enable the old moderation checklist. -->
<!-- <ModerationChecklist <!-- <ModerationChecklist
@ -895,6 +885,7 @@
</div> </div>
</div> </div>
</div> </div>
<div <div
v-if="auth.user && tags.staffRoles.includes(auth.user.role) && showModerationChecklist" v-if="auth.user && tags.staffRoles.includes(auth.user.role) && showModerationChecklist"
class="moderation-checklist" class="moderation-checklist"
@ -908,6 +899,7 @@
/> />
</div> </div>
</template> </template>
<script setup> <script setup>
import { import {
BookmarkIcon, BookmarkIcon,
@ -1570,8 +1562,6 @@ async function copyPermalink() {
const collapsedChecklist = ref(false); const collapsedChecklist = ref(false);
console.log(project.value.id);
const showModerationChecklist = useLocalStorage( const showModerationChecklist = useLocalStorage(
`show-moderation-checklist-${project.value.id}`, `show-moderation-checklist-${project.value.id}`,
false, false,
@ -1663,6 +1653,7 @@ const navLinks = computed(() => {
]; ];
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.settings-header { .settings-header {
display: flex; display: flex;

View File

@ -1421,7 +1421,8 @@ useSeoMeta({
width: 25rem; width: 25rem;
height: 25rem; height: 25rem;
opacity: 0.75; opacity: 0.75;
background: radial-gradient( background:
radial-gradient(
50% 50% at 50% 50%, 50% 50% at 50% 50%,
rgba(5, 206, 69, 0.19) 0%, rgba(5, 206, 69, 0.19) 0%,
rgba(15, 19, 49, 0.25) 100% rgba(15, 19, 49, 0.25) 100%

View File

@ -266,12 +266,12 @@ const getRangeOfMethod = (method) => {
const maxWithdrawAmount = computed(() => { const maxWithdrawAmount = computed(() => {
const interval = selectedMethod.value.interval; const interval = selectedMethod.value.interval;
return interval?.standard ? interval.standard.max : interval?.fixed?.values.slice(-1)[0] ?? 0; return interval?.standard ? interval.standard.max : (interval?.fixed?.values.slice(-1)[0] ?? 0);
}); });
const minWithdrawAmount = computed(() => { const minWithdrawAmount = computed(() => {
const interval = selectedMethod.value.interval; const interval = selectedMethod.value.interval;
return interval?.standard ? interval.standard.min : interval?.fixed?.values?.[0] ?? fees.value; return interval?.standard ? interval.standard.min : (interval?.fixed?.values?.[0] ?? fees.value);
}); });
const withdrawAccount = computed(() => { const withdrawAccount = computed(() => {

View File

@ -149,7 +149,8 @@ onMounted(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.main-hero { .main-hero {
background: linear-gradient(360deg, rgba(199, 138, 255, 0.2) 10.92%, var(--color-bg) 100%), background:
linear-gradient(360deg, rgba(199, 138, 255, 0.2) 10.92%, var(--color-bg) 100%),
var(--color-accent-contrast); var(--color-accent-contrast);
margin-top: -5rem; margin-top: -5rem;
padding: 11.25rem 1rem 8rem; padding: 11.25rem 1rem 8rem;

View File

@ -1020,7 +1020,7 @@ const nodeUnavailableDetails = computed(() => [
{ {
label: "Error message", label: "Error message",
value: nodeAccessible.value value: nodeAccessible.value
? server.moduleErrors?.general?.error.message ?? "Unknown" ? (server.moduleErrors?.general?.error.message ?? "Unknown")
: "Unable to reach node. Ping test failed.", : "Unable to reach node. Ping test failed.",
type: "block" as const, type: "block" as const,
}, },
@ -1277,7 +1277,8 @@ useHead({
background-repeat: no-repeat; background-repeat: no-repeat;
filter: blur(1rem); filter: blur(1rem);
content: ""; content: "";
background-image: linear-gradient( background-image:
linear-gradient(
to bottom, to bottom,
rgba(from var(--color-raised-bg) r g b / 0.2), rgba(from var(--color-raised-bg) r g b / 0.2),
rgb(from var(--color-raised-bg) r g b / 0.8) rgb(from var(--color-raised-bg) r g b / 0.8)

View File

@ -101,7 +101,7 @@
<span :class="{ invisible: 'current_file' in op && !op.current_file }"> <span :class="{ invisible: 'current_file' in op && !op.current_file }">
{{ {{
"current_file" in op "current_file" in op
? op.current_file?.split("/")?.pop() ?? "unknown" ? (op.current_file?.split("/")?.pop() ?? "unknown")
: "unknown" : "unknown"
}} }}
</span> </span>

View File

@ -80,11 +80,6 @@ export interface ConditionalMessage extends WeightedMessage {
*/ */
excludedActions?: string[] excludedActions?: string[]
} }
/**
* Fallback message if conditions are not met.
*/
fallbackMessage?: () => Promise<typeof import('*.md?raw') | string>
} }
/** /**
@ -146,6 +141,16 @@ export interface ConditionalButtonAction extends BaseAction {
* Different message configurations based on conditions. * Different message configurations based on conditions.
*/ */
messageVariants: ConditionalMessage[] messageVariants: ConditionalMessage[]
/**
* Global fallback message if no variants match their conditions.
*/
fallbackMessage?: () => Promise<string>
/**
* The weight of the action's fallback message, used to determine the place where the message is placed in the final moderation message.
*/
fallbackWeight?: number
} }
export interface DropdownActionOption extends WeightedMessage { export interface DropdownActionOption extends WeightedMessage {

View File

@ -126,6 +126,7 @@ export function findMatchingVariant(
variants: ConditionalMessage[], variants: ConditionalMessage[],
selectedActionIds: string[], selectedActionIds: string[],
allValidActionIds?: string[], allValidActionIds?: string[],
currentStageIndex?: number,
): ConditionalMessage | null { ): ConditionalMessage | null {
for (const variant of variants) { for (const variant of variants) {
const conditions = variant.conditions const conditions = variant.conditions
@ -133,22 +134,33 @@ export function findMatchingVariant(
const meetsRequired = const meetsRequired =
!conditions.requiredActions || !conditions.requiredActions ||
conditions.requiredActions.every((id) => { conditions.requiredActions.every((id) => {
if (allValidActionIds && !allValidActionIds.includes(id)) { let fullId = id
if (currentStageIndex !== undefined && !id.startsWith('stage-')) {
fullId = `stage-${currentStageIndex}-${id}`
}
if (allValidActionIds && !allValidActionIds.includes(fullId)) {
return false return false
} }
return selectedActionIds.includes(id) return selectedActionIds.includes(fullId)
}) })
const meetsExcluded = const meetsExcluded =
!conditions.excludedActions || !conditions.excludedActions ||
!conditions.excludedActions.some((id) => selectedActionIds.includes(id)) !conditions.excludedActions.some((id) => {
let fullId = id
if (currentStageIndex !== undefined && !id.startsWith('stage-')) {
fullId = `stage-${currentStageIndex}-${id}`
}
return selectedActionIds.includes(fullId)
})
if (meetsRequired && meetsExcluded) { if (meetsRequired && meetsExcluded) {
return variant return variant
} }
} }
return variants.find((v) => v.fallbackMessage) || null return null
} }
export async function getActionMessage( export async function getActionMessage(

38
pnpm-lock.yaml generated
View File

@ -187,7 +187,7 @@ importers:
dependencies: dependencies:
'@astrojs/check': '@astrojs/check':
specifier: ^0.9.4 specifier: ^0.9.4
version: 0.9.4(prettier@3.3.2)(typescript@5.8.2) version: 0.9.4(prettier@3.6.2)(typescript@5.8.2)
'@astrojs/starlight': '@astrojs/starlight':
specifier: ^0.32.2 specifier: ^0.32.2
version: 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0)) version: 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0))
@ -284,6 +284,9 @@ importers:
pinia: pinia:
specifier: ^2.1.7 specifier: ^2.1.7
version: 2.1.7(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4)) version: 2.1.7(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4))
prettier:
specifier: ^3.6.2
version: 3.6.2
qrcode.vue: qrcode.vue:
specifier: ^3.4.0 specifier: ^3.4.0
version: 3.4.1(vue@3.5.13(typescript@5.5.4)) version: 3.4.1(vue@3.5.13(typescript@5.5.4))
@ -347,7 +350,7 @@ importers:
version: 8.4.49 version: 8.4.49
prettier-plugin-tailwindcss: prettier-plugin-tailwindcss:
specifier: ^0.6.5 specifier: ^0.6.5
version: 0.6.5(prettier@3.3.2) version: 0.6.5(prettier@3.6.2)
sass: sass:
specifier: ^1.58.0 specifier: ^1.58.0
version: 1.77.6 version: 1.77.6
@ -447,7 +450,7 @@ importers:
version: 2.0.7(eslint@9.13.0(jiti@2.4.2)) version: 2.0.7(eslint@9.13.0(jiti@2.4.2))
eslint-plugin-prettier: eslint-plugin-prettier:
specifier: ^5.2.1 specifier: ^5.2.1
version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2))(prettier@3.3.2) version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2))(prettier@3.6.2)
eslint-plugin-unicorn: eslint-plugin-unicorn:
specifier: ^54.0.0 specifier: ^54.0.0
version: 54.0.0(eslint@9.13.0(jiti@2.4.2)) version: 54.0.0(eslint@9.13.0(jiti@2.4.2))
@ -6692,6 +6695,11 @@ packages:
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
prettier@3.6.2:
resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
engines: {node: '>=14'}
hasBin: true
pretty-bytes@6.1.1: pretty-bytes@6.1.1:
resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
engines: {node: ^14.13.1 || >=16.0.0} engines: {node: ^14.13.1 || >=16.0.0}
@ -8555,9 +8563,9 @@ snapshots:
'@apidevtools/swagger-methods@3.0.2': {} '@apidevtools/swagger-methods@3.0.2': {}
'@astrojs/check@0.9.4(prettier@3.3.2)(typescript@5.8.2)': '@astrojs/check@0.9.4(prettier@3.6.2)(typescript@5.8.2)':
dependencies: dependencies:
'@astrojs/language-server': 2.15.4(prettier@3.3.2)(typescript@5.8.2) '@astrojs/language-server': 2.15.4(prettier@3.6.2)(typescript@5.8.2)
chokidar: 4.0.1 chokidar: 4.0.1
kleur: 4.1.5 kleur: 4.1.5
typescript: 5.8.2 typescript: 5.8.2
@ -8572,7 +8580,7 @@ snapshots:
'@astrojs/internal-helpers@0.6.0': {} '@astrojs/internal-helpers@0.6.0': {}
'@astrojs/language-server@2.15.4(prettier@3.3.2)(typescript@5.8.2)': '@astrojs/language-server@2.15.4(prettier@3.6.2)(typescript@5.8.2)':
dependencies: dependencies:
'@astrojs/compiler': 2.10.3 '@astrojs/compiler': 2.10.3
'@astrojs/yaml2ts': 0.2.2 '@astrojs/yaml2ts': 0.2.2
@ -8586,14 +8594,14 @@ snapshots:
volar-service-css: 0.0.62(@volar/language-service@2.4.11) volar-service-css: 0.0.62(@volar/language-service@2.4.11)
volar-service-emmet: 0.0.62(@volar/language-service@2.4.11) volar-service-emmet: 0.0.62(@volar/language-service@2.4.11)
volar-service-html: 0.0.62(@volar/language-service@2.4.11) volar-service-html: 0.0.62(@volar/language-service@2.4.11)
volar-service-prettier: 0.0.62(@volar/language-service@2.4.11)(prettier@3.3.2) volar-service-prettier: 0.0.62(@volar/language-service@2.4.11)(prettier@3.6.2)
volar-service-typescript: 0.0.62(@volar/language-service@2.4.11) volar-service-typescript: 0.0.62(@volar/language-service@2.4.11)
volar-service-typescript-twoslash-queries: 0.0.62(@volar/language-service@2.4.11) volar-service-typescript-twoslash-queries: 0.0.62(@volar/language-service@2.4.11)
volar-service-yaml: 0.0.62(@volar/language-service@2.4.11) volar-service-yaml: 0.0.62(@volar/language-service@2.4.11)
vscode-html-languageservice: 5.3.1 vscode-html-languageservice: 5.3.1
vscode-uri: 3.0.8 vscode-uri: 3.0.8
optionalDependencies: optionalDependencies:
prettier: 3.3.2 prettier: 3.6.2
transitivePeerDependencies: transitivePeerDependencies:
- typescript - typescript
@ -12990,10 +12998,10 @@ snapshots:
resolve: 1.22.8 resolve: 1.22.8
semver: 6.3.1 semver: 6.3.1
eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2))(prettier@3.3.2): eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2))(prettier@3.6.2):
dependencies: dependencies:
eslint: 9.13.0(jiti@2.4.2) eslint: 9.13.0(jiti@2.4.2)
prettier: 3.3.2 prettier: 3.6.2
prettier-linter-helpers: 1.0.0 prettier-linter-helpers: 1.0.0
synckit: 0.9.1 synckit: 0.9.1
optionalDependencies: optionalDependencies:
@ -15958,15 +15966,17 @@ snapshots:
dependencies: dependencies:
fast-diff: 1.3.0 fast-diff: 1.3.0
prettier-plugin-tailwindcss@0.6.5(prettier@3.3.2): prettier-plugin-tailwindcss@0.6.5(prettier@3.6.2):
dependencies: dependencies:
prettier: 3.3.2 prettier: 3.6.2
prettier@2.8.7: prettier@2.8.7:
optional: true optional: true
prettier@3.3.2: {} prettier@3.3.2: {}
prettier@3.6.2: {}
pretty-bytes@6.1.1: {} pretty-bytes@6.1.1: {}
prismjs@1.29.0: {} prismjs@1.29.0: {}
@ -17639,12 +17649,12 @@ snapshots:
optionalDependencies: optionalDependencies:
'@volar/language-service': 2.4.11 '@volar/language-service': 2.4.11
volar-service-prettier@0.0.62(@volar/language-service@2.4.11)(prettier@3.3.2): volar-service-prettier@0.0.62(@volar/language-service@2.4.11)(prettier@3.6.2):
dependencies: dependencies:
vscode-uri: 3.0.8 vscode-uri: 3.0.8
optionalDependencies: optionalDependencies:
'@volar/language-service': 2.4.11 '@volar/language-service': 2.4.11
prettier: 3.3.2 prettier: 3.6.2
volar-service-typescript-twoslash-queries@0.0.62(@volar/language-service@2.4.11): volar-service-typescript-twoslash-queries@0.0.62(@volar/language-service@2.4.11):
dependencies: dependencies: