feat: start on frontend impl
This commit is contained in:
parent
b98c1fe7b8
commit
bcfceecf1b
@ -1,9 +1,12 @@
|
||||
<template>
|
||||
<div v-if="showInvitation" class="universal-card information invited">
|
||||
<h2>Invitation to join project</h2>
|
||||
<p>
|
||||
You've been invited be a member of this project with the role of '{{ currentMember.role }}'.
|
||||
<p v-if="currentMember?.project_role">
|
||||
You've been invited be a member of this project with the role of '{{
|
||||
currentMember.project_role
|
||||
}}'.
|
||||
</p>
|
||||
<p v-else>You've been invited to join this project. Please accept or decline the invitation.</p>
|
||||
<div class="input-group">
|
||||
<button class="iconified-button brand-button" @click="acceptInvite()">
|
||||
<CheckIcon />
|
||||
@ -18,73 +21,67 @@
|
||||
<div
|
||||
v-if="
|
||||
currentMember &&
|
||||
nags.filter((x) => x.condition).length > 0 &&
|
||||
visibleNags.length > 0 &&
|
||||
(project.status === 'draft' || tags.rejectedStatuses.includes(project.status))
|
||||
"
|
||||
class="author-actions universal-card mb-4"
|
||||
class="universal-card mb-4"
|
||||
>
|
||||
<div class="header__row">
|
||||
<div class="header__title">
|
||||
<h2>Publishing checklist</h2>
|
||||
<div class="checklist">
|
||||
<span class="checklist__title">Progress:</span>
|
||||
<div class="checklist__items">
|
||||
<div class="flex max-w-full flex-wrap items-center gap-x-6 gap-y-4">
|
||||
<div class="flex flex-auto flex-wrap items-center gap-x-6 gap-y-4">
|
||||
<h2 class="my-0 mr-auto">Publishing checklist</h2>
|
||||
<div class="flex w-fit max-w-full flex-row flex-wrap items-center gap-2">
|
||||
<span class="mr-2 font-bold text-dark">Progress:</span>
|
||||
<div class="flex w-fit max-w-full flex-row items-center gap-2">
|
||||
<div
|
||||
v-for="nag in nags"
|
||||
v-for="nag in applicableNags"
|
||||
:key="`checklist-${nag.id}`"
|
||||
v-tooltip="nag.title"
|
||||
:aria-label="nag.title"
|
||||
:class="'circle ' + (!nag.condition ? 'done' : '') + nag.status"
|
||||
class="circle"
|
||||
:class="[
|
||||
'flex h-8 w-8 items-center justify-center rounded-full transition-colors',
|
||||
isNagComplete(nag)
|
||||
? 'bg-green text-inverted'
|
||||
: nag.status === 'required'
|
||||
? 'bg-bg text-red'
|
||||
: nag.status === 'warning'
|
||||
? 'bg-bg text-orange'
|
||||
: 'bg-bg text-purple',
|
||||
]"
|
||||
>
|
||||
<CheckIcon v-if="!nag.condition" />
|
||||
<AsteriskIcon v-else-if="nag.status === 'required'" />
|
||||
<LightBulbIcon v-else-if="nag.status === 'suggestion'" />
|
||||
<ScaleIcon v-else-if="nag.status === 'review'" />
|
||||
<CheckIcon v-if="isNagComplete(nag)" class="h-4 w-4" />
|
||||
<component :is="nag.icon || getDefaultIcon(nag.status)" v-else class="h-4 w-4" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<button
|
||||
:class="{ 'not-collapsed': !collapsed }"
|
||||
class="square-button"
|
||||
:class="['square-button', !collapsed && '[&>svg]:rotate-180']"
|
||||
@click="toggleCollapsed()"
|
||||
>
|
||||
<DropdownIcon />
|
||||
<DropdownIcon class="duration-250 transition-transform ease-in-out" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!collapsed" class="grid-display width-16">
|
||||
<div
|
||||
v-for="nag in nags.filter((x) => x.condition && !x.hide)"
|
||||
:key="nag.id"
|
||||
class="grid-display__item"
|
||||
>
|
||||
<span class="label">
|
||||
<AsteriskIcon
|
||||
v-if="nag.status === 'required'"
|
||||
v-tooltip="'Required'"
|
||||
:class="nag.status"
|
||||
aria-label="Required"
|
||||
<div v-for="nag in visibleNags" :key="nag.id" class="grid-display__item">
|
||||
<span class="flex items-center gap-2">
|
||||
<component
|
||||
:is="nag.icon || getDefaultIcon(nag.status)"
|
||||
v-tooltip="getStatusTooltip(nag.status)"
|
||||
:class="[
|
||||
'h-4 w-4',
|
||||
nag.status === 'required' && 'text-red',
|
||||
nag.status === 'warning' && 'text-orange',
|
||||
nag.status === 'suggestion' && 'text-purple',
|
||||
]"
|
||||
:aria-label="getStatusTooltip(nag.status)"
|
||||
/>
|
||||
<LightBulbIcon
|
||||
v-else-if="nag.status === 'suggestion'"
|
||||
v-tooltip="'Suggestion'"
|
||||
:class="nag.status"
|
||||
aria-label="Suggestion"
|
||||
/>
|
||||
<ScaleIcon
|
||||
v-else-if="nag.status === 'review'"
|
||||
v-tooltip="'Review'"
|
||||
:class="nag.status"
|
||||
aria-label="Review"
|
||||
/>{{ nag.title }}</span
|
||||
>
|
||||
{{ nag.description }}
|
||||
{{ nag.title }}
|
||||
</span>
|
||||
{{ nag.description(nagContext) }}
|
||||
<NuxtLink
|
||||
v-if="nag.link"
|
||||
:class="{ invisible: nag.link.hide }"
|
||||
v-if="nag.link && shouldShowLink(nag)"
|
||||
:to="`/${project.project_type}/${project.slug ? project.slug : project.id}/${
|
||||
nag.link.path
|
||||
}`"
|
||||
@ -93,418 +90,207 @@
|
||||
{{ nag.link.title }}
|
||||
<ChevronRightIcon aria-hidden="true" class="featured-header-chevron" />
|
||||
</NuxtLink>
|
||||
<button
|
||||
v-else-if="nag.action"
|
||||
:disabled="nag.action.disabled()"
|
||||
class="btn btn-orange"
|
||||
@click="nag.action.onClick"
|
||||
>
|
||||
<SendIcon />
|
||||
{{ nag.action.title }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
CheckIcon,
|
||||
XIcon,
|
||||
AsteriskIcon,
|
||||
LightBulbIcon,
|
||||
SendIcon,
|
||||
ScaleIcon,
|
||||
TriangleAlertIcon,
|
||||
DropdownIcon,
|
||||
} from "@modrinth/assets";
|
||||
import { formatProjectType } from "@modrinth/utils";
|
||||
import { acceptTeamInvite, removeTeamMember } from "~/helpers/teams.js";
|
||||
import { nags } from "@modrinth/moderation";
|
||||
import type { Nag, NagContext, NagStatus } from "@modrinth/moderation";
|
||||
import type { Project, User, Version } from "@modrinth/utils";
|
||||
import type { Component } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
project: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
versions: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
currentMember: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
allMembers: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
isSettings: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
routeName: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
auth: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
tags: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
setProcessing: {
|
||||
type: Function,
|
||||
default() {
|
||||
return () => {
|
||||
addNotification({
|
||||
group: "main",
|
||||
title: "An error occurred",
|
||||
text: "setProcessing function not found",
|
||||
type: "error",
|
||||
});
|
||||
interface Tags {
|
||||
rejectedStatuses: string[];
|
||||
}
|
||||
|
||||
interface Auth {
|
||||
user: {
|
||||
id: string;
|
||||
};
|
||||
},
|
||||
},
|
||||
toggleCollapsed: {
|
||||
type: Function,
|
||||
default() {
|
||||
return () => {
|
||||
addNotification({
|
||||
group: "main",
|
||||
title: "An error occurred",
|
||||
text: "toggleCollapsed function not found",
|
||||
type: "error",
|
||||
});
|
||||
};
|
||||
},
|
||||
},
|
||||
updateMembers: {
|
||||
type: Function,
|
||||
default() {
|
||||
return () => {
|
||||
addNotification({
|
||||
group: "main",
|
||||
title: "An error occurred",
|
||||
text: "updateMembers function not found",
|
||||
type: "error",
|
||||
});
|
||||
};
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface Member {
|
||||
accepted?: boolean;
|
||||
project_role?: string;
|
||||
user?: Partial<User>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
project: Project;
|
||||
versions?: Version[];
|
||||
currentMember?: Member | null;
|
||||
allMembers?: Member[] | null;
|
||||
isSettings?: boolean;
|
||||
collapsed?: boolean;
|
||||
routeName?: string;
|
||||
auth: Auth;
|
||||
tags: Tags;
|
||||
setProcessing?: (processing: boolean) => void;
|
||||
toggleCollapsed?: () => void;
|
||||
updateMembers?: () => void | Promise<void>;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
versions: () => [],
|
||||
currentMember: null,
|
||||
allMembers: null,
|
||||
isSettings: false,
|
||||
collapsed: false,
|
||||
routeName: "",
|
||||
});
|
||||
|
||||
const featuredGalleryImage = computed(() => props.project.gallery.find((img) => img.featured));
|
||||
const emit = defineEmits<{
|
||||
toggleCollapsed: [];
|
||||
updateMembers: [];
|
||||
setProcessing: [processing: boolean];
|
||||
}>();
|
||||
|
||||
const nags = computed(() => [
|
||||
{
|
||||
condition: props.versions.length < 1,
|
||||
title: "Upload a version",
|
||||
id: "upload-version",
|
||||
description: "At least one version is required for a project to be submitted for review.",
|
||||
status: "required",
|
||||
link: {
|
||||
path: "versions",
|
||||
title: "Visit versions page",
|
||||
hide: props.routeName === "type-id-versions",
|
||||
},
|
||||
},
|
||||
{
|
||||
condition:
|
||||
props.project.body === "" || props.project.body.startsWith("# Placeholder description"),
|
||||
title: "Add a description",
|
||||
id: "add-description",
|
||||
description:
|
||||
"A description that clearly describes the project's purpose and function is required.",
|
||||
status: "required",
|
||||
link: {
|
||||
path: "settings/description",
|
||||
title: "Visit description settings",
|
||||
hide: props.routeName === "type-id-settings-description",
|
||||
},
|
||||
},
|
||||
{
|
||||
condition: !props.project.icon_url,
|
||||
title: "Add an icon",
|
||||
id: "add-icon",
|
||||
description:
|
||||
"Your project should have a nice-looking icon to uniquely identify your project at a glance.",
|
||||
status: "suggestion",
|
||||
link: {
|
||||
path: "settings",
|
||||
title: "Visit general settings",
|
||||
hide: props.routeName === "type-id-settings",
|
||||
},
|
||||
},
|
||||
{
|
||||
condition: props.project.gallery.length === 0 || !featuredGalleryImage,
|
||||
title: "Feature a gallery image",
|
||||
id: "feature-gallery-image",
|
||||
description: "Featured gallery images may be the first impression of many users.",
|
||||
status: "suggestion",
|
||||
link: {
|
||||
path: "gallery",
|
||||
title: "Visit gallery page",
|
||||
hide: props.routeName === "type-id-gallery",
|
||||
},
|
||||
},
|
||||
{
|
||||
hide: props.project.versions.length === 0,
|
||||
condition: props.project.categories.length < 1,
|
||||
title: "Select tags",
|
||||
id: "select-tags",
|
||||
description: "Select all tags that apply to your project.",
|
||||
status: "suggestion",
|
||||
link: {
|
||||
path: "settings/tags",
|
||||
title: "Visit tag settings",
|
||||
hide: props.routeName === "type-id-settings-tags",
|
||||
},
|
||||
},
|
||||
{
|
||||
condition: !(
|
||||
props.project.issues_url ||
|
||||
props.project.source_url ||
|
||||
props.project.wiki_url ||
|
||||
props.project.discord_url ||
|
||||
props.project.donation_urls.length > 0
|
||||
),
|
||||
title: "Add external links",
|
||||
id: "add-links",
|
||||
description:
|
||||
"Add any relevant links targeted outside of Modrinth, such as sources, issues, or a Discord invite.",
|
||||
status: "suggestion",
|
||||
link: {
|
||||
path: "settings/links",
|
||||
title: "Visit links settings",
|
||||
hide: props.routeName === "type-id-settings-links",
|
||||
},
|
||||
},
|
||||
{
|
||||
hide:
|
||||
props.project.versions.length === 0 ||
|
||||
props.project.project_type === "resourcepack" ||
|
||||
props.project.project_type === "plugin" ||
|
||||
props.project.project_type === "shader" ||
|
||||
props.project.project_type === "datapack",
|
||||
condition:
|
||||
props.project.client_side === "unknown" ||
|
||||
props.project.server_side === "unknown" ||
|
||||
(props.project.client_side === "unsupported" && props.project.server_side === "unsupported"),
|
||||
title: "Select supported environments",
|
||||
id: "select-environments",
|
||||
description: `Select if the ${formatProjectType(
|
||||
props.project.project_type,
|
||||
).toLowerCase()} functions on the client-side and/or server-side.`,
|
||||
status: "required",
|
||||
link: {
|
||||
path: "settings",
|
||||
title: "Visit general settings",
|
||||
hide: props.routeName === "type-id-settings",
|
||||
},
|
||||
},
|
||||
{
|
||||
condition: props.project.license.id === "LicenseRef-Unknown",
|
||||
title: "Select license",
|
||||
id: "select-license",
|
||||
description: `Select the license your ${formatProjectType(
|
||||
props.project.project_type,
|
||||
).toLowerCase()} is distributed under.`,
|
||||
status: "required",
|
||||
link: {
|
||||
path: "settings/license",
|
||||
title: "Visit license settings",
|
||||
hide: props.routeName === "type-id-settings-license",
|
||||
},
|
||||
},
|
||||
{
|
||||
condition: props.project.status === "draft",
|
||||
title: "Submit for review",
|
||||
id: "submit-for-review",
|
||||
description:
|
||||
"Your project is only viewable by members of the project. It must be reviewed by moderators in order to be published.",
|
||||
status: "review",
|
||||
link: null,
|
||||
action: {
|
||||
onClick: submitForReview,
|
||||
title: "Submit for review",
|
||||
disabled: () => nags.value.filter((x) => x.condition && x.status === "required").length > 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
hide: props.project.stats === "draft",
|
||||
condition: props.tags.rejectedStatuses.includes(props.project.status),
|
||||
title: "Resubmit for review",
|
||||
id: "resubmit-for-review",
|
||||
description: `Your project has been ${props.project.status} by
|
||||
Modrinth's staff. In most cases, you can resubmit for review after
|
||||
addressing the staff's message.`,
|
||||
status: "review",
|
||||
link: {
|
||||
path: "moderation",
|
||||
title: "Visit moderation page",
|
||||
hide: props.routeName === "type-id-moderation",
|
||||
},
|
||||
},
|
||||
]);
|
||||
const nagContext = computed<NagContext>(() => ({
|
||||
project: props.project,
|
||||
versions: props.versions,
|
||||
currentMember: props.currentMember as User,
|
||||
currentRoute: props.routeName,
|
||||
}));
|
||||
|
||||
const showInvitation = computed(() => {
|
||||
const applicableNags = computed<Nag[]>(() => {
|
||||
return nags.filter((nag) => {
|
||||
return !nag.shouldShow || nag.shouldShow(nagContext.value);
|
||||
});
|
||||
});
|
||||
|
||||
const isNagComplete = (nag: Nag): boolean => {
|
||||
const context = nagContext.value;
|
||||
};
|
||||
|
||||
const visibleNags = computed<Nag[]>(() => {
|
||||
return applicableNags.value.filter((nag) => !isNagComplete(nag));
|
||||
});
|
||||
|
||||
const shouldShowLink = (nag: Nag): boolean => {
|
||||
if (!nag.link) return false;
|
||||
if (!nag.link.shouldShow) return true;
|
||||
return nag.link.shouldShow(nagContext.value);
|
||||
};
|
||||
|
||||
const getDefaultIcon = (status: NagStatus): Component => {
|
||||
switch (status) {
|
||||
case "required":
|
||||
return AsteriskIcon;
|
||||
case "warning":
|
||||
return TriangleAlertIcon;
|
||||
case "suggestion":
|
||||
return LightBulbIcon;
|
||||
default:
|
||||
return AsteriskIcon;
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusTooltip = (status: NagStatus): string => {
|
||||
switch (status) {
|
||||
case "required":
|
||||
return "Required";
|
||||
case "warning":
|
||||
return "Warning";
|
||||
case "suggestion":
|
||||
return "Suggestion";
|
||||
default:
|
||||
return "Required";
|
||||
}
|
||||
};
|
||||
|
||||
const showInvitation = computed<boolean>(() => {
|
||||
if (props.allMembers && props.auth) {
|
||||
const member = props.allMembers.find((x) => x.user.id === props.auth.user.id);
|
||||
return member && !member.accepted;
|
||||
return !!member && !member.accepted;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const acceptInvite = () => {
|
||||
acceptTeamInvite(props.project.team);
|
||||
props.updateMembers();
|
||||
const toggleCollapsed = (): void => {
|
||||
if (props.toggleCollapsed) {
|
||||
props.toggleCollapsed();
|
||||
} else {
|
||||
emit("toggleCollapsed");
|
||||
}
|
||||
};
|
||||
|
||||
const declineInvite = () => {
|
||||
removeTeamMember(props.project.team, props.auth.user.id);
|
||||
props.updateMembers();
|
||||
const updateMembers = async (): Promise<void> => {
|
||||
if (props.updateMembers) {
|
||||
await props.updateMembers();
|
||||
} else {
|
||||
emit("updateMembers");
|
||||
}
|
||||
};
|
||||
|
||||
const submitForReview = async () => {
|
||||
if (
|
||||
!props.acknowledgedMessage ||
|
||||
nags.value.filter((x) => x.condition && x.status === "required").length === 0
|
||||
) {
|
||||
await props.setProcessing();
|
||||
const setProcessing = (processing: boolean): void => {
|
||||
if (props.setProcessing) {
|
||||
props.setProcessing(processing);
|
||||
} else {
|
||||
emit("setProcessing", processing);
|
||||
}
|
||||
};
|
||||
|
||||
const acceptInvite = async (): Promise<void> => {
|
||||
try {
|
||||
setProcessing(true);
|
||||
await acceptTeamInvite(props.project.team);
|
||||
await updateMembers();
|
||||
addNotification({
|
||||
group: "main",
|
||||
title: "Success",
|
||||
text: "You have joined the project team",
|
||||
type: "success",
|
||||
});
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
group: "main",
|
||||
title: "Error",
|
||||
text: "Failed to accept team invitation",
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
setProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
const declineInvite = async (): Promise<void> => {
|
||||
try {
|
||||
setProcessing(true);
|
||||
await removeTeamMember(props.project.team, props.auth.user.id);
|
||||
await updateMembers();
|
||||
addNotification({
|
||||
group: "main",
|
||||
title: "Success",
|
||||
text: "You have declined the team invitation",
|
||||
type: "success",
|
||||
});
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
group: "main",
|
||||
title: "Error",
|
||||
text: "Failed to decline team invitation",
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
setProcessing(false);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.invited {
|
||||
}
|
||||
|
||||
.author-actions {
|
||||
margin-top: var(--spacing-card-md);
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.header__row {
|
||||
align-items: center;
|
||||
column-gap: var(--spacing-card-lg);
|
||||
row-gap: var(--spacing-card-md);
|
||||
max-width: 100%;
|
||||
|
||||
.header__title {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
column-gap: var(--spacing-card-lg);
|
||||
row-gap: var(--spacing-card-md);
|
||||
flex-basis: min-content;
|
||||
|
||||
h2 {
|
||||
margin: 0 auto 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
svg {
|
||||
transition: transform 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
&.not-collapsed svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.grid-display__item .label {
|
||||
display: flex;
|
||||
gap: var(--spacing-card-xs);
|
||||
align-items: center;
|
||||
|
||||
.required {
|
||||
color: var(--color-red);
|
||||
}
|
||||
|
||||
.suggestion {
|
||||
color: var(--color-purple);
|
||||
}
|
||||
|
||||
.review {
|
||||
color: var(--color-orange);
|
||||
}
|
||||
}
|
||||
|
||||
.checklist {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--spacing-card-xs);
|
||||
width: fit-content;
|
||||
flex-wrap: wrap;
|
||||
max-width: 100%;
|
||||
|
||||
.checklist__title {
|
||||
font-weight: bold;
|
||||
margin-right: var(--spacing-card-xs);
|
||||
color: var(--color-text-dark);
|
||||
}
|
||||
|
||||
.checklist__items {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--spacing-card-xs);
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.circle {
|
||||
--circle-size: 2rem;
|
||||
--background-color: var(--color-bg);
|
||||
--content-color: var(--color-gray);
|
||||
width: var(--circle-size);
|
||||
height: var(--circle-size);
|
||||
border-radius: 50%;
|
||||
background-color: var(--background-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
color: var(--content-color);
|
||||
width: calc(var(--circle-size) / 2);
|
||||
height: calc(var(--circle-size) / 2);
|
||||
}
|
||||
|
||||
&.required {
|
||||
--content-color: var(--color-red);
|
||||
}
|
||||
|
||||
&.suggestion {
|
||||
--content-color: var(--color-purple);
|
||||
}
|
||||
|
||||
&.review {
|
||||
--content-color: var(--color-orange);
|
||||
}
|
||||
|
||||
&.done {
|
||||
--background-color: var(--color-green);
|
||||
--content-color: var(--color-brand-inverted);
|
||||
}
|
||||
}
|
||||
}
|
||||
.duration-250 {
|
||||
transition-duration: 250ms;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1360,6 +1360,8 @@ const currentMember = computed(() => {
|
||||
};
|
||||
}
|
||||
|
||||
console.log("Current member:", val);
|
||||
|
||||
return val;
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user