fix: compile error + notif binding issue
This commit is contained in:
parent
a11c58274c
commit
1602aa9556
@ -15,7 +15,7 @@
|
|||||||
maxlength="64"
|
maxlength="64"
|
||||||
:placeholder="`Enter organization name...`"
|
:placeholder="`Enter organization name...`"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
@input="updateSlug()"
|
@input="updateSlug"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
@ -33,7 +33,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
maxlength="64"
|
maxlength="64"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
@input="manualSlug = true"
|
@input="setManualSlug"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -61,7 +61,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</ButtonStyled>
|
</ButtonStyled>
|
||||||
<ButtonStyled>
|
<ButtonStyled>
|
||||||
<button @click="modal.hide()">
|
<button @click="hide">
|
||||||
<XIcon aria-hidden="true" />
|
<XIcon aria-hidden="true" />
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
@ -70,21 +70,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</NewModal>
|
</NewModal>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
|
||||||
|
<script setup lang="ts">
|
||||||
import { PlusIcon, XIcon } from "@modrinth/assets";
|
import { PlusIcon, XIcon } from "@modrinth/assets";
|
||||||
import { ButtonStyled, NewModal } from "@modrinth/ui";
|
import { ButtonStyled, NewModal, injectNotificationManager } from "@modrinth/ui";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
const router = useNativeRouter();
|
const router = useNativeRouter();
|
||||||
const { addNotification } = injectNotificationManager();
|
const { addNotification } = injectNotificationManager();
|
||||||
|
|
||||||
const name = ref("");
|
const name = ref<string>("");
|
||||||
const slug = ref("");
|
const slug = ref<string>("");
|
||||||
const description = ref("");
|
const description = ref<string>("");
|
||||||
const manualSlug = ref(false);
|
const manualSlug = ref<boolean>(false);
|
||||||
|
const modal = ref<InstanceType<typeof NewModal>>();
|
||||||
|
|
||||||
const modal = ref();
|
async function createOrganization(): Promise<void> {
|
||||||
|
|
||||||
async function createOrganization() {
|
|
||||||
startLoading();
|
startLoading();
|
||||||
try {
|
try {
|
||||||
const value = {
|
const value = {
|
||||||
@ -93,16 +94,16 @@ async function createOrganization() {
|
|||||||
slug: slug.value.trim().replace(/ +/g, ""),
|
slug: slug.value.trim().replace(/ +/g, ""),
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await useBaseFetch("organization", {
|
const result: any = await useBaseFetch("organization", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify(value),
|
body: JSON.stringify(value),
|
||||||
apiVersion: 3,
|
apiVersion: 3,
|
||||||
});
|
});
|
||||||
|
|
||||||
modal.value.hide();
|
modal.value?.hide();
|
||||||
|
|
||||||
await router.push(`/organization/${result.slug}`);
|
await router.push(`/organization/${result.slug}`);
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
addNotification({
|
addNotification({
|
||||||
title: "An error occurred",
|
title: "An error occurred",
|
||||||
@ -112,13 +113,18 @@ async function createOrganization() {
|
|||||||
}
|
}
|
||||||
stopLoading();
|
stopLoading();
|
||||||
}
|
}
|
||||||
function show(event) {
|
|
||||||
|
function show(event?: MouseEvent): void {
|
||||||
name.value = "";
|
name.value = "";
|
||||||
description.value = "";
|
description.value = "";
|
||||||
modal.value.show(event);
|
modal.value?.show(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSlug() {
|
function hide(): void {
|
||||||
|
modal.value?.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSlug(): void {
|
||||||
if (!manualSlug.value) {
|
if (!manualSlug.value) {
|
||||||
slug.value = name.value
|
slug.value = name.value
|
||||||
.trim()
|
.trim()
|
||||||
@ -129,6 +135,10 @@ function updateSlug() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setManualSlug(): void {
|
||||||
|
manualSlug.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
show,
|
show,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { injectNotificationManager } from "@modrinth/ui";
|
|
||||||
|
|
||||||
export const useUser = async (force = false) => {
|
export const useUser = async (force = false) => {
|
||||||
const user = useState("user", () => {});
|
const user = useState("user", () => {});
|
||||||
|
|
||||||
@ -137,7 +135,8 @@ export const userFollowProject = async (project) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const resendVerifyEmail = async () => {
|
export const resendVerifyEmail = async () => {
|
||||||
const { addNotification } = injectNotificationManager();
|
// const { injectNotificationManager } = await import("@modrinth/ui");
|
||||||
|
// const { addNotification } = injectNotificationManager();
|
||||||
|
|
||||||
startLoading();
|
startLoading();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,19 +1,14 @@
|
|||||||
import { injectNotificationManager } from "@modrinth/ui";
|
import { injectNotificationManager } from "@modrinth/ui";
|
||||||
|
import type { Organization, Project, Report, User, Version } from "@modrinth/utils";
|
||||||
|
|
||||||
// TODO: There needs to be a standardized way to get these types, eg; @modrinth/types generated from api schema. Later problem.
|
|
||||||
type Project = { id: string };
|
|
||||||
type Version = { id: string; project_id: string };
|
|
||||||
type Report = { id: string; item_type: "project" | "user" | "version"; item_id: string };
|
|
||||||
type Thread = { id: string };
|
type Thread = { id: string };
|
||||||
type User = { id: string };
|
|
||||||
type Organization = { id: string };
|
|
||||||
|
|
||||||
export type NotificationAction = {
|
export type PlatformNotificationAction = {
|
||||||
title: string;
|
title: string;
|
||||||
action_route: [string, string];
|
action_route: [string, string];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NotificationBody = {
|
export type PlatformNotificationBody = {
|
||||||
project_id?: string;
|
project_id?: string;
|
||||||
version_id?: string;
|
version_id?: string;
|
||||||
report_id?: string;
|
report_id?: string;
|
||||||
@ -22,7 +17,7 @@ export type NotificationBody = {
|
|||||||
organization_id?: string;
|
organization_id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Notification = {
|
export type PlatformNotification = {
|
||||||
id: string;
|
id: string;
|
||||||
user_id: string;
|
user_id: string;
|
||||||
type: "project_update" | "team_invite" | "status_change" | "moderator_message";
|
type: "project_update" | "team_invite" | "status_change" | "moderator_message";
|
||||||
@ -31,10 +26,10 @@ export type Notification = {
|
|||||||
link: string;
|
link: string;
|
||||||
read: boolean;
|
read: boolean;
|
||||||
created: string;
|
created: string;
|
||||||
actions: NotificationAction[];
|
actions: PlatformNotificationAction[];
|
||||||
body?: NotificationBody;
|
body?: PlatformNotificationBody;
|
||||||
extra_data?: Record<string, unknown>;
|
extra_data?: Record<string, unknown>;
|
||||||
grouped_notifs?: Notification[];
|
grouped_notifs?: PlatformNotification[];
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getBulk<T extends { id: string }>(
|
async function getBulk<T extends { id: string }>(
|
||||||
@ -55,8 +50,8 @@ async function getBulk<T extends { id: string }>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchExtraNotificationData(
|
export async function fetchExtraNotificationData(
|
||||||
notifications: Notification[],
|
notifications: PlatformNotification[],
|
||||||
): Promise<Notification[]> {
|
): Promise<PlatformNotification[]> {
|
||||||
const bulk = {
|
const bulk = {
|
||||||
projects: [] as string[],
|
projects: [] as string[],
|
||||||
reports: [] as string[],
|
reports: [] as string[],
|
||||||
@ -133,8 +128,8 @@ export async function fetchExtraNotificationData(
|
|||||||
return notifications;
|
return notifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function groupNotifications(notifications: Notification[]): Notification[] {
|
export function groupNotifications(notifications: PlatformNotification[]): PlatformNotification[] {
|
||||||
const grouped: Notification[] = [];
|
const grouped: PlatformNotification[] = [];
|
||||||
for (let i = 0; i < notifications.length; i++) {
|
for (let i = 0; i < notifications.length; i++) {
|
||||||
const current = notifications[i];
|
const current = notifications[i];
|
||||||
const next = notifications[i + 1];
|
const next = notifications[i + 1];
|
||||||
@ -154,18 +149,18 @@ export function groupNotifications(notifications: Notification[]): Notification[
|
|||||||
return grouped;
|
return grouped;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSimilar(a: Notification, b: Notification | undefined): boolean {
|
function isSimilar(a: PlatformNotification, b: PlatformNotification | undefined): boolean {
|
||||||
return !!a?.body?.project_id && a.body!.project_id === b?.body?.project_id;
|
return !!a?.body?.project_id && a.body!.project_id === b?.body?.project_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function markAsRead(
|
export async function markAsRead(
|
||||||
ids: string[],
|
ids: string[],
|
||||||
): Promise<(notifications: Notification[]) => Notification[]> {
|
): Promise<(notifications: PlatformNotification[]) => PlatformNotification[]> {
|
||||||
try {
|
try {
|
||||||
await useBaseFetch(`notifications?ids=${JSON.stringify([...new Set(ids)])}`, {
|
await useBaseFetch(`notifications?ids=${JSON.stringify([...new Set(ids)])}`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
});
|
});
|
||||||
return (notifications: Notification[]) => {
|
return (notifications: PlatformNotification[]) => {
|
||||||
const newNotifs = notifications ?? [];
|
const newNotifs = notifications ?? [];
|
||||||
newNotifs.forEach((n) => {
|
newNotifs.forEach((n) => {
|
||||||
if (ids.includes(n.id)) n.read = true;
|
if (ids.includes(n.id)) n.read = true;
|
||||||
|
|||||||
@ -1552,11 +1552,15 @@ const collapsedModerationChecklist = useLocalStorage("collapsed-moderation-check
|
|||||||
watch(
|
watch(
|
||||||
showModerationChecklist,
|
showModerationChecklist,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
notifications.setNotificationsPanelRightwards(newValue);
|
notifications.setNotificationLocation(newValue ? "left" : "right");
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
notifications.setNotificationLocation("right");
|
||||||
|
});
|
||||||
|
|
||||||
if (import.meta.client && history && history.state && history.state.showChecklist) {
|
if (import.meta.client && history && history.state && history.state.showChecklist) {
|
||||||
showModerationChecklist.value = true;
|
showModerationChecklist.value = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,28 +1,32 @@
|
|||||||
import { type WebNotification, AbstractWebNotificationManager } from "@modrinth/ui";
|
|
||||||
import { useState } from "#app";
|
import { useState } from "#app";
|
||||||
|
import {
|
||||||
|
type WebNotification,
|
||||||
|
type WebNotificationLocation,
|
||||||
|
AbstractWebNotificationManager,
|
||||||
|
} from "@modrinth/ui";
|
||||||
|
|
||||||
export class FrontendNotificationManager extends AbstractWebNotificationManager {
|
export class FrontendNotificationManager extends AbstractWebNotificationManager {
|
||||||
private readonly state: Ref<WebNotification[]>;
|
private readonly state: Ref<WebNotification[]>;
|
||||||
private readonly isRightwards: Ref<boolean>;
|
private readonly locationState: Ref<WebNotificationLocation>;
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = useState<WebNotification[]>("notifications", () => []);
|
this.state = useState<WebNotification[]>("notifications", () => []);
|
||||||
this.isRightwards = useState<boolean>("notifications.isRightwards", () => true);
|
this.locationState = useState<WebNotificationLocation>("notifications.location", () => "right");
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNotificationLocation(): WebNotificationLocation {
|
||||||
|
return this.locationState.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setNotificationLocation(location: WebNotificationLocation): void {
|
||||||
|
this.locationState.value = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getNotifications(): WebNotification[] {
|
public getNotifications(): WebNotification[] {
|
||||||
return this.state.value;
|
return this.state.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isNotificationsPanelRightwards(): boolean {
|
|
||||||
return this.isRightwards.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public setNotificationsPanelRightwards(isRightwards: boolean): void {
|
|
||||||
this.isRightwards.value = isRightwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected addNotificationToStorage(notification: WebNotification): void {
|
protected addNotificationToStorage(notification: WebNotification): void {
|
||||||
this.state.value.push(notification);
|
this.state.value.push(notification);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="vue-notification-group experimental-styles-within"
|
class="vue-notification-group experimental-styles-within"
|
||||||
:class="{ 'intercom-present': isIntercomPresent }"
|
:class="{
|
||||||
|
'intercom-present': isIntercomPresent,
|
||||||
|
'location-left': notificationLocation === 'left',
|
||||||
|
'location-right': notificationLocation === 'right',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<transition-group name="notifs">
|
<transition-group name="notifs">
|
||||||
<div
|
<div
|
||||||
@ -72,20 +76,21 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, onMounted, onBeforeUnmount } from 'vue'
|
|
||||||
import { ButtonStyled, injectNotificationManager, type WebNotification } from '@modrinth/ui'
|
|
||||||
import {
|
import {
|
||||||
XCircleIcon,
|
|
||||||
CheckCircleIcon,
|
CheckCircleIcon,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
|
CopyIcon,
|
||||||
InfoIcon,
|
InfoIcon,
|
||||||
IssuesIcon,
|
IssuesIcon,
|
||||||
|
XCircleIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
CopyIcon,
|
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
|
import { ButtonStyled, injectNotificationManager, type WebNotification } from '@modrinth/ui'
|
||||||
|
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
|
|
||||||
const notificationManager = injectNotificationManager()
|
const notificationManager = injectNotificationManager()
|
||||||
const notifications = computed<WebNotification[]>(() => notificationManager.getNotifications())
|
const notifications = computed<WebNotification[]>(() => notificationManager.getNotifications())
|
||||||
|
const notificationLocation = computed(() => notificationManager.getNotificationLocation())
|
||||||
|
|
||||||
const isIntercomPresent = ref<boolean>(false)
|
const isIntercomPresent = ref<boolean>(false)
|
||||||
const copied = ref<Record<string, boolean>>({})
|
const copied = ref<Record<string, boolean>>({})
|
||||||
@ -134,15 +139,31 @@ onMounted(() => {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.vue-notification-group {
|
.vue-notification-group {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 1.5rem;
|
|
||||||
bottom: 1.5rem;
|
bottom: 1.5rem;
|
||||||
z-index: 200;
|
z-index: 200;
|
||||||
width: 450px;
|
width: 450px;
|
||||||
|
|
||||||
|
&.location-right {
|
||||||
|
right: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.location-left {
|
||||||
|
left: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 500px) {
|
@media screen and (max-width: 500px) {
|
||||||
width: calc(100% - 0.75rem * 2);
|
width: calc(100% - 0.75rem * 2);
|
||||||
right: 0.75rem;
|
|
||||||
bottom: 0.75rem;
|
bottom: 0.75rem;
|
||||||
|
|
||||||
|
&.location-right {
|
||||||
|
right: 0.75rem;
|
||||||
|
left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.location-left {
|
||||||
|
left: 0.75rem;
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.intercom-present {
|
&.intercom-present {
|
||||||
@ -184,6 +205,12 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.notifs-leave-to {
|
.notifs-leave-to {
|
||||||
transform: translateX(100%) scale(0.8);
|
.location-right & {
|
||||||
|
transform: translateX(100%) scale(0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.location-left & {
|
||||||
|
transform: translateX(-100%) scale(0.8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -10,17 +10,21 @@ export interface WebNotification {
|
|||||||
timer?: NodeJS.Timeout
|
timer?: NodeJS.Timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type WebNotificationLocation = 'left' | 'right'
|
||||||
|
|
||||||
export abstract class AbstractWebNotificationManager {
|
export abstract class AbstractWebNotificationManager {
|
||||||
protected readonly AUTO_DISMISS_DELAY_MS = 30 * 1000
|
protected readonly AUTO_DISMISS_DELAY_MS = 30 * 1000
|
||||||
|
|
||||||
abstract getNotifications(): WebNotification[]
|
abstract getNotifications(): WebNotification[]
|
||||||
|
abstract getNotificationLocation(): WebNotificationLocation
|
||||||
|
abstract setNotificationLocation(location: WebNotificationLocation): void
|
||||||
|
|
||||||
protected abstract addNotificationToStorage(notification: WebNotification): void
|
protected abstract addNotificationToStorage(notification: WebNotification): void
|
||||||
protected abstract removeNotificationFromStorage(id: string | number): void
|
protected abstract removeNotificationFromStorage(id: string | number): void
|
||||||
protected abstract removeNotificationFromStorageByIndex(index: number): void
|
protected abstract removeNotificationFromStorageByIndex(index: number): void
|
||||||
protected abstract clearAllNotificationsFromStorage(): void
|
protected abstract clearAllNotificationsFromStorage(): void
|
||||||
|
|
||||||
addNotification(notification: Partial<WebNotification>): void {
|
addNotification = (notification: Partial<WebNotification>): void => {
|
||||||
const existingNotif = this.findExistingNotification(notification)
|
const existingNotif = this.findExistingNotification(notification)
|
||||||
|
|
||||||
if (existingNotif) {
|
if (existingNotif) {
|
||||||
@ -34,7 +38,7 @@ export abstract class AbstractWebNotificationManager {
|
|||||||
this.addNotificationToStorage(newNotification)
|
this.addNotificationToStorage(newNotification)
|
||||||
}
|
}
|
||||||
|
|
||||||
removeNotification(id: string | number): void {
|
removeNotification = (id: string | number): void => {
|
||||||
const notifications = this.getNotifications()
|
const notifications = this.getNotifications()
|
||||||
const notification = notifications.find((n) => n.id === id)
|
const notification = notifications.find((n) => n.id === id)
|
||||||
|
|
||||||
@ -44,7 +48,7 @@ export abstract class AbstractWebNotificationManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeNotificationByIndex(index: number): void {
|
removeNotificationByIndex = (index: number): void => {
|
||||||
const notifications = this.getNotifications()
|
const notifications = this.getNotifications()
|
||||||
|
|
||||||
if (index >= 0 && index < notifications.length) {
|
if (index >= 0 && index < notifications.length) {
|
||||||
@ -54,7 +58,7 @@ export abstract class AbstractWebNotificationManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearAllNotifications(): void {
|
clearAllNotifications = (): void => {
|
||||||
const notifications = this.getNotifications()
|
const notifications = this.getNotifications()
|
||||||
notifications.forEach((notification) => {
|
notifications.forEach((notification) => {
|
||||||
this.clearNotificationTimer(notification)
|
this.clearNotificationTimer(notification)
|
||||||
@ -62,7 +66,7 @@ export abstract class AbstractWebNotificationManager {
|
|||||||
this.clearAllNotificationsFromStorage()
|
this.clearAllNotificationsFromStorage()
|
||||||
}
|
}
|
||||||
|
|
||||||
setNotificationTimer(notification: WebNotification): void {
|
setNotificationTimer = (notification: WebNotification): void => {
|
||||||
if (!notification) return
|
if (!notification) return
|
||||||
|
|
||||||
this.clearNotificationTimer(notification)
|
this.clearNotificationTimer(notification)
|
||||||
@ -72,7 +76,7 @@ export abstract class AbstractWebNotificationManager {
|
|||||||
}, this.AUTO_DISMISS_DELAY_MS)
|
}, this.AUTO_DISMISS_DELAY_MS)
|
||||||
}
|
}
|
||||||
|
|
||||||
stopNotificationTimer(notification: WebNotification): void {
|
stopNotificationTimer = (notification: WebNotification): void => {
|
||||||
this.clearNotificationTimer(notification)
|
this.clearNotificationTimer(notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user