Allow editing existing icons

Co-authored-by: ajnart <49837342+ajnart@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-08 23:25:59 +00:00
parent 38bbd4663e
commit 7357a1f2c2
3 changed files with 22 additions and 17 deletions

View File

@@ -5,6 +5,14 @@ import { BASE_URL, WEB_URL } from "@/constants"
import { getAllIcons, getAuthorData } from "@/lib/api"
import { getCommunityGalleryRecord, getCommunitySubmissionByName, getCommunitySubmissions } from "@/lib/community"
function isIconAddedToCollection(
record: Awaited<ReturnType<typeof getCommunityGalleryRecord>>,
collectionIcons: Record<string, unknown>,
icon: string,
) {
return record?.status === "added_to_collection" && Object.hasOwn(collectionIcons, icon)
}
export const dynamicParams = true
export const revalidate = 21600 // 6 hours
export const dynamic = "force-static"
@@ -30,7 +38,10 @@ export async function generateMetadata({ params }: Props, _parent: ResolvingMeta
}
const record = await getCommunityGalleryRecord(icon)
if (record?.status === "added_to_collection") {
const collectionIcons = await getAllIcons()
const isInCollection = isIconAddedToCollection(record, collectionIcons, icon)
if (isInCollection) {
permanentRedirect(`/icons/${icon}`)
}
@@ -118,12 +129,12 @@ export default async function CommunityIconPage({ params }: { params: Promise<{
}
const record = await getCommunityGalleryRecord(icon)
if (record?.status === "added_to_collection") {
const allIcons = await getAllIcons()
const isInCollection = isIconAddedToCollection(record, allIcons, icon)
if (isInCollection) {
permanentRedirect(`/icons/${icon}`)
}
const allIcons = await getAllIcons()
const author = iconData.data.update.author as any
const githubId = author?.github_id
const authorMetaLogin = author?.login || author?.name

View File

@@ -27,7 +27,6 @@ import { MultiSelect, type MultiSelectOption } from "@/components/ui/multi-selec
import { Dropzone, DropzoneContent, DropzoneEmptyState } from "@/components/ui/shadcn-io/dropzone"
import { Textarea } from "@/components/ui/textarea"
import { REPO_PATH } from "@/constants"
import { useExistingIconNames } from "@/hooks/use-submissions"
import { pb } from "@/lib/pb"
interface VariantConfig {
@@ -112,7 +111,6 @@ interface FormData {
export function AdvancedIconSubmissionFormTanStack() {
const [filePreviews, setFilePreviews] = useState<Record<string, string>>({})
const [showConfirmDialog, setShowConfirmDialog] = useState(false)
const { data: existingIcons = [] } = useExistingIconNames()
const router = useRouter()
const form = useForm({
@@ -383,11 +381,6 @@ export function AdvancedIconSubmissionFormTanStack() {
if (!/^[a-z0-9-]+$/.test(value)) {
return "Icon name must contain only lowercase letters, numbers, and hyphens"
}
// Check if icon already exists
const iconExists = existingIcons.some((icon) => icon.value === value)
if (iconExists) {
return "This icon already exists. Icon updates are not yet supported. Please choose a different name."
}
return undefined
},
}}
@@ -676,7 +669,7 @@ export function AdvancedIconSubmissionFormTanStack() {
>
{(state) => (
<Button type="submit" disabled={!state.canSubmit || state.isSubmitting} size="lg">
{state.isSubmitting ? "Submitting..." : "Submit New Icon"}
{state.isSubmitting ? "Submitting..." : "Submit Icon"}
</Button>
)}
</form.Subscribe>

View File

@@ -65,7 +65,7 @@ export function IconNameCombobox({ value, onValueChange, error, isInvalid }: Ico
// Delay to allow clicking on suggestions
setTimeout(() => setIsFocused(false), 200)
}}
placeholder="Type new icon ID (e.g., my-app)..."
placeholder="Type icon ID (new or existing, e.g., my-app)..."
className={cn("font-mono", isInvalid && "border-destructive focus-visible:ring-destructive/50")}
aria-invalid={isInvalid}
aria-describedby={error ? "icon-name-error" : undefined}
@@ -77,7 +77,7 @@ export function IconNameCombobox({ value, onValueChange, error, isInvalid }: Ico
<Command className="rounded-md">
<CommandList className="max-h-[300px] overflow-y-auto">
<CommandEmpty>No existing icons found</CommandEmpty>
<CommandGroup heading={`⚠️ Existing Icons (${filteredIcons.length} matches - Not Allowed)`}>
<CommandGroup heading={`Existing Icons (${filteredIcons.length} matches)`}>
{filteredIcons.slice(0, 50).map((icon) => (
<CommandItem
key={icon.value}
@@ -87,9 +87,8 @@ export function IconNameCombobox({ value, onValueChange, error, isInvalid }: Ico
onValueChange(selectedValue)
setIsFocused(false)
}}
className="cursor-pointer opacity-60"
className="cursor-pointer"
>
<AlertCircle className="h-3.5 w-3.5 text-destructive mr-2 flex-shrink-0" />
<span className="font-mono text-sm">{icon.label}</span>
</CommandItem>
))}
@@ -109,7 +108,9 @@ export function IconNameCombobox({ value, onValueChange, error, isInvalid }: Ico
{/* Helper text when no error */}
{!error && value && (
<p className="text-sm text-muted-foreground mt-1.5">{loading ? "Checking availability..." : "✓ Available icon ID"}</p>
<p className="text-sm text-muted-foreground mt-1.5">
{loading ? "Loading icon names..." : "Select an existing icon to update or enter a new ID"}
</p>
)}
</div>
)