fix: link checks merge conflict issues

This commit is contained in:
tdgao
2026-08-24 16:19:49 -07:00
committed by Prospector
parent 4b2f8dedec
commit e618c1625a
7 changed files with 975 additions and 798 deletions
@@ -141,14 +141,7 @@
:original="saved"
:modified="current"
:saving="saving"
:can-save="
hasPermission &&
!(
current.license.friendly === 'Custom' &&
(current.license.short === '' || current.licenseUrl === '')
) &&
effectiveLicenseCheck?.severity !== 'error'
"
:can-save="canSave"
@reset="reset"
@save="save"
/>
@@ -156,7 +149,7 @@
</template>
<script setup lang="ts">
import { useLinkCheck } from '@modrinth/moderation'
import { isLinkCheckPending, useLinkCheck } from '@modrinth/moderation'
import {
Checkbox,
Combobox,
@@ -207,7 +200,14 @@ function getInitialLicense() {
)
}
const { saved, current, saving, hasChanges, reset, save } = useSavable(
const {
saved,
current,
saving,
hasChanges,
reset,
save: saveLicense,
} = useSavable(
() => ({
license: getInitialLicense(),
licenseUrl: project.value.license.url ?? '',
@@ -232,14 +232,13 @@ const { saved, current, saving, hasChanges, reset, save } = useSavable(
},
)
const effectiveLicenseCheck = useLinkCheck(
computed(() => ({
field: 'license',
url: current.value.licenseUrl,
expectedLicense: current.value.license.short,
isCustom: current.value.license.friendly === 'Custom',
})),
)
const licenseContext = computed(() => ({
field: 'license',
url: current.value.licenseUrl,
expectedLicense: current.value.license.short,
isCustom: current.value.license.friendly === 'Custom',
}))
const effectiveLicenseCheck = useLinkCheck(licenseContext)
const { confirmLeaveModal } = usePageLeaveSafety(hasChanges)
@@ -255,6 +254,22 @@ const hasPermission = computed(() => {
return (currentMember.value?.permissions ?? 0) & TeamMemberPermission.EDIT_DETAILS
})
const canSave = computed(
() =>
Boolean(hasPermission.value) &&
!(
current.value.license.friendly === 'Custom' &&
(current.value.license.short === '' || current.value.licenseUrl === '')
) &&
effectiveLicenseCheck.value?.severity !== 'error' &&
!isLinkCheckPending(licenseContext.value),
)
async function save() {
if (!canSave.value) return
await saveLicense()
}
const licenseId = computed(() => {
let id = ''
@@ -69,17 +69,6 @@
/>
<LinkCheckMessage :check="discordInviteCheck" />
</div>
<div class="mt-3 flex flex-wrap justify-start gap-2">
<Button
type="colored"
color="brand"
:disabled="!hasServerChanges"
@click="saveServerChanges()"
>
<SaveIcon />
Save changes
</Button>
</div>
</section>
<!-- Standard Project Links -->
@@ -190,13 +179,7 @@
class="platform-selector !w-80"
@update:model-value="updateDonationLinks"
/>
</div>
<LinkCheckMessage :check="donationCheckState(donationLink, index)" />
<div class="mt-3 flex flex-wrap justify-start gap-2">
<Button type="colored" color="brand" :disabled="!hasChanges" @click="saveChanges()">
<SaveIcon />
Save changes
</Button>
<LinkCheckMessage :check="donationCheckState(donationLink, index)" />
</div>
</section>
<UnsavedChangesPopup
@@ -354,16 +337,25 @@ function donationCheckState(row, index) {
return getLinkCheckState(donationContext(row))
}
const donationCheckTimers = new Map()
const donationCheckTimers = reactive(new Map())
onScopeDispose(() => {
for (const timeout of donationCheckTimers.values()) clearTimeout(timeout)
})
watch(
donationLinks,
(rows) => {
for (const timeout of donationCheckTimers.values()) clearTimeout(timeout)
donationCheckTimers.clear()
rows.forEach((row, index) => {
if (!row.id || !row.url) return
clearTimeout(donationCheckTimers.get(index))
donationCheckTimers.set(
index,
setTimeout(() => checkLink(donationContext(row)), 500),
setTimeout(() => {
donationCheckTimers.delete(index)
void checkLink(donationContext(row))
}, 500),
)
})
},
@@ -411,14 +403,21 @@ function donationRowsToObject(rows) {
const donationsSavedRows = computed(() => donationRowsFromLinks(project.value?.link_urls))
const original = computed(() => ({
...saved.value,
...(isServerProject.value ? {} : donationRowsToObject(donationsSavedRows.value)),
}))
const modified = computed(() => ({
...current.value,
...(isServerProject.value ? {} : donationRowsToObject(donationLinks.value)),
}))
const originalDonationRows = computed(() =>
isServerProject.value ? {} : donationRowsToObject(donationsSavedRows.value),
)
const modifiedDonationRows = computed(() =>
isServerProject.value ? {} : donationRowsToObject(donationLinks.value),
)
const original = computed(() => ({ ...saved.value, ...originalDonationRows.value }))
const modified = computed(() => {
const donations = { ...modifiedDonationRows.value }
for (const key of Object.keys(originalDonationRows.value)) {
if (!(key in donations)) donations[key] = undefined
}
return { ...current.value, ...donations }
})
const hasChanges = computed(() =>
Object.keys(modified.value).some((key) => modified.value[key] !== original.value[key]),
@@ -459,9 +458,11 @@ const canSave = computed(() => {
donationLinks.value.some((row, index) => donationCheckState(row, index)?.severity === 'error')
const donationsPending =
!isServerProject.value &&
donationLinks.value.some((row) => isLinkCheckPending(donationContext(row)))
(donationCheckTimers.size > 0 ||
donationLinks.value.some((row) => isLinkCheckPending(donationContext(row))))
return (
hasPermission.value &&
!fieldsInvalid &&
!fieldsPending &&
!donationsInvalid &&
@@ -473,6 +474,7 @@ const canSave = computed(() => {
const saving = ref(false)
async function save() {
if (!canSave.value) return
const data = patchData.value
if (Object.keys(data).length === 0) return