/****************************************************************************** * Copyright (c) 2026 Contributors to the Eclipse Foundation. * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * https://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 *****************************************************************************/ import { FunctionComponent, useContext, useState } from 'react'; import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material'; import { ButtonWithProgress } from '../button-with-progress'; import { MainContext } from '../../context'; import { Extension, VersionTargetPlatforms } from '../../extension-registry-types'; import { VersionDeleteTarget } from './extension-version-delete-dialog'; import { isConflictError } from './extension-version-dialog-shared'; export const DeleteAllVersionsDialog: FunctionComponent = props => { const { handleError } = useContext(MainContext); const [working, setWorking] = useState(false); const isPurge = (props.mode ?? 'delete') === 'purge'; const handleRemove = async () => { try { setWorking(true); // Delete (soft) only applies to versions still present; purge can also target already-removed ones. const targets: VersionDeleteTarget[] = props.versions.flatMap(v => v.targetPlatforms .filter(tp => isPurge || !tp.removed) .map(({ targetPlatform }) => ({ version: v.version, targetPlatform })) ); await props.onRemove(targets); props.onDeleted(); props.onClose(); } catch (err) { if (isConflictError(err)) { // The underlying data is stale; keep this dialog open behind the error // dialog and only close/refresh once the user acknowledges it. handleError(err, { onClose: () => { props.onDeleted(); props.onClose(); } }); } else { handleError(err); } } finally { setWorking(false); } }; return ( {isPurge ? 'Purge' : 'Delete'} all versions of {props.extension.displayName ?? props.extension.name}? {isPurge ? `This permanently removes ${props.versions.length} version` + `${props.versions.length === 1 ? '' : 's'} of this extension from the database and storage ` + 'across all target platforms, freeing the version numbers so they can be published again. ' + 'This cannot be undone.' : `This removes ${props.versions.length} version` + `${props.versions.length === 1 ? '' : 's'} of this extension across all target platforms and ` + 'deletes their files. Extension versions are immutable, so removed versions stay ' + 'permanently reserved and can never be republished. This cannot be undone.'} {isPurge ? 'Purge All Versions' : 'Delete All Versions'} ); }; export interface DeleteAllVersionsDialogProps { open: boolean; onClose: () => void; extension: Extension; versions: VersionTargetPlatforms[]; onRemove: (targets: VersionDeleteTarget[]) => Promise; onDeleted: () => void; // 'delete' (default) soft-deletes; 'purge' permanently removes (admin only). mode?: 'delete' | 'purge'; }