Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ const props = defineProps<{
const emit = defineEmits<{
complete: [];
"update:modelValue": [judgements: ModerationJudgements];
"update:allFiles": [
allFiles: { interactive: ModerationModpackItem[]; permanentNo: ModerationModpackItem[] },
];
}>();

const persistedModPackData = useLocalStorage<ModerationModpackItem[] | null>(
Expand All @@ -183,6 +186,7 @@ const persistedModPackData = useLocalStorage<ModerationModpackItem[] | null>(
const persistedIndex = useLocalStorage<number>(`modpack-permissions-index-${props.projectId}`, 0);

const modPackData = ref<ModerationModpackItem[] | null>(null);
const permanentNoFiles = ref<ModerationModpackItem[]>([]);
const currentIndex = ref(0);

const fileApprovalTypes: ModerationModpackPermissionApprovalType[] = [
Expand Down Expand Up @@ -251,7 +255,45 @@ async function fetchModPackData(): Promise<void> {
const data = (await useBaseFetch(`moderation/project/${props.projectId}`, {
internal: true,
})) as ModerationModpackResponse;

const permanentNoItems: ModerationModpackItem[] = Object.entries(data.identified || {})
.filter(([_, file]) => file.status === "permanent-no")
.map(
([sha1, file]): ModerationModpackItem => ({
sha1,
file_name: file.file_name,
type: "identified",
status: file.status,
approved: null,
}),
)
.sort((a, b) => a.file_name.localeCompare(b.file_name));

permanentNoFiles.value = permanentNoItems;

const sortedData: ModerationModpackItem[] = [
...Object.entries(data.identified || {})
.filter(
([_, file]) =>
file.status !== "yes" &&
file.status !== "with-attribution-and-source" &&
file.status !== "permanent-no",
)
.map(
([sha1, file]): ModerationModpackItem => ({
sha1,
file_name: file.file_name,
type: "identified",
status: file.status,
approved: null,
...(file.status === "unidentified" && {
proof: "",
url: "",
title: "",
}),
}),
)
.sort((a, b) => a.file_name.localeCompare(b.file_name)),
...Object.entries(data.unknown_files || {})
.map(
([sha1, fileName]): ModerationUnknownModpackItem => ({
Expand Down Expand Up @@ -310,6 +352,7 @@ async function fetchModPackData(): Promise<void> {
} catch (error) {
console.error("Failed to fetch modpack data:", error);
modPackData.value = [];
permanentNoFiles.value = [];
persistAll();
}
}
Expand All @@ -321,13 +364,32 @@ function goToPrevious(): void {
}
}

function emitAllFiles(): void {
if (modPackData.value) {
emit("update:allFiles", {
interactive: modPackData.value,
permanentNo: permanentNoFiles.value,
});
}
}

watch(
modPackData,
(newValue) => {
persistedModPackData.value = newValue;
emitAllFiles();
},
{ deep: true },
);

function goToNext(): void {
if (modPackData.value && currentIndex.value < modPackData.value.length) {
currentIndex.value++;

if (currentIndex.value >= modPackData.value.length) {
const judgements = getJudgements();
emit("update:modelValue", judgements);
emitAllFiles();
emit("complete");
clearPersistedData();
} else {
Expand All @@ -342,6 +404,7 @@ function setStatus(index: number, status: ModerationModpackPermissionApprovalTyp
modPackData.value[index].approved = null;
persistAll();
emit("update:modelValue", getJudgements());
emitAllFiles();
}
}

Expand All @@ -350,6 +413,7 @@ function setApproval(index: number, approved: ModerationPermissionType["id"]): v
modPackData.value[index].approved = approved;
persistAll();
emit("update:modelValue", getJudgements());
emitAllFiles();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
v-model="modpackJudgements"
:project-id="project.id"
@complete="handleModpackPermissionsComplete"
@update:allFiles="allModpackFiles = $event"
/>
</div>
<div v-else>
Expand Down Expand Up @@ -240,24 +241,6 @@
</div>

<div v-else-if="generatedMessage" class="flex items-center gap-2">
<OverflowMenu :options="stageOptions" class="bg-transparent p-0">
<ButtonStyled circular>
<button v-tooltip="`Stages`">
<ListBulletedIcon />
</button>
</ButtonStyled>

<template
v-for="opt in stageOptions.filter(
(opt) => 'id' in opt && 'text' in opt && 'icon' in opt,
)"
#[opt.id]
:key="opt.id"
>
<component :is="opt.icon" v-if="opt.icon" class="mr-2" />
{{ opt.text }}
</template>
</OverflowMenu>
<ButtonStyled>
<button @click="goBackToStages">
<LeftArrowIcon aria-hidden="true" />
Expand Down Expand Up @@ -368,7 +351,12 @@ import {
DropdownSelect,
MarkdownEditor,
} from "@modrinth/ui";
import { type Project, renderHighlightedString, type ModerationJudgements } from "@modrinth/utils";
import {
type Project,
renderHighlightedString,
type ModerationJudgements,
type ModerationModpackItem,
} from "@modrinth/utils";
import { computedAsync, useLocalStorage } from "@vueuse/core";
import type {
Action,
Expand Down Expand Up @@ -408,6 +396,13 @@ const futureProjectCount = computed(() => {

const modpackPermissionsComplete = ref(false);
const modpackJudgements = ref<ModerationJudgements>({});
const allModpackFiles = ref<{
interactive: ModerationModpackItem[];
permanentNo: ModerationModpackItem[];
}>({
interactive: [],
permanentNo: [],
});
const isModpackPermissionsStage = computed(() => {
return currentStageObj.value.id === "modpack-permissions";
});
Expand Down Expand Up @@ -441,6 +436,7 @@ function resetProgress() {
localStorage.removeItem(`modpack-permissions-index-${props.project.id}`);
modpackPermissionsComplete.value = false;
modpackJudgements.value = {};
allModpackFiles.value = { interactive: [], permanentNo: [] };

initializeAllStages();
}
Expand Down Expand Up @@ -1082,9 +1078,9 @@ async function generateMessage() {

if (
props.project.project_type === "modpack" &&
Object.keys(modpackJudgements.value).length > 0
(allModpackFiles.value.interactive.length > 0 || allModpackFiles.value.permanentNo.length > 0)
) {
const modpackMessage = generateModpackMessage(modpackJudgements.value);
const modpackMessage = generateModpackMessage(allModpackFiles.value);
if (modpackMessage) {
fullMessage = baseMessage ? `${baseMessage}\n\n${modpackMessage}` : modpackMessage;
}
Expand Down Expand Up @@ -1117,25 +1113,30 @@ async function generateMessage() {
}
}

function generateModpackMessage(judgements: ModerationJudgements) {
function generateModpackMessage(allFiles: {
interactive: ModerationModpackItem[];
permanentNo: ModerationModpackItem[];
}) {
const issues = [];

const attributeMods = [];
const noMods = [];
const permanentNoMods = [];
const unidentifiedMods = [];

for (const [, judgement] of Object.entries(judgements)) {
if (judgement.status === "with-attribution") {
attributeMods.push(judgement.file_name);
} else if (judgement.status === "no") {
noMods.push(judgement.file_name);
} else if (judgement.status === "permanent-no") {
permanentNoMods.push(judgement.file_name);
} else if (judgement.status === "unidentified") {
unidentifiedMods.push(judgement.file_name);
const attributeMods: string[] = [];
const noMods: string[] = [];
const permanentNoMods: string[] = [];
const unidentifiedMods: string[] = [];

allFiles.interactive.forEach((file) => {
if (file.status === "with-attribution" && !file.approved) {
attributeMods.push(file.file_name);
} else if (file.status === "no" && !file.approved) {
noMods.push(file.file_name);
} else if (file.status === "unidentified" && !file.approved) {
unidentifiedMods.push(file.file_name);
}
}
});

allFiles.permanentNo.forEach((file) => {
permanentNoMods.push(file.file_name);
});

if (
attributeMods.length > 0 ||
Expand Down
25 changes: 21 additions & 4 deletions packages/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ export interface ModerationPermissionType {
export interface ModerationBaseModpackItem {
sha1: string
file_name: string
type: 'unknown' | 'flame'
type: 'unknown' | 'flame' | 'identified'
status: ModerationModpackPermissionApprovalType['id'] | null
approved: ModerationPermissionType['id'] | null
}
Expand All @@ -334,9 +334,26 @@ export interface ModerationFlameModpackItem extends ModerationBaseModpackItem {
url: string
}

export type ModerationModpackItem = ModerationUnknownModpackItem | ModerationFlameModpackItem
export interface ModerationIdentifiedModpackItem extends ModerationBaseModpackItem {
type: 'identified'
proof?: string
url?: string
title?: string
}

export type ModerationModpackItem =
| ModerationUnknownModpackItem
| ModerationFlameModpackItem
| ModerationIdentifiedModpackItem

export interface ModerationModpackResponse {
identified?: Record<
string,
{
file_name: string
status: ModerationModpackPermissionApprovalType['id']
}
>
unknown_files?: Record<string, string>
flame_files?: Record<
string,
Expand All @@ -350,8 +367,8 @@ export interface ModerationModpackResponse {
}

export interface ModerationJudgement {
type: 'flame' | 'unknown'
status: string
type: 'flame' | 'unknown' | 'identified'
status: string | null
id?: string
link?: string
title?: string
Expand Down