mirror of
https://github.com/arcan1s/ahriman.git
synced 2026-03-16 14:53:38 +00:00
feat: dynamic package hold (#160)
* add dynamic hold implementation to backend * update frontend to support new status * force reporter loader * handle missing packages explicitly * handle missing packages explicitly
This commit is contained in:
@@ -78,6 +78,14 @@ export class ServiceClient {
|
||||
return this.client.request("/api/v1/service/pgp", { method: "POST", json: data });
|
||||
}
|
||||
|
||||
async servicePackageHoldUpdate(packageBase: string, repository: RepositoryId, isHeld: boolean): Promise<void> {
|
||||
return this.client.request(`/api/v1/packages/${encodeURIComponent(packageBase)}/hold`, {
|
||||
method: "POST",
|
||||
query: repository.toQuery(),
|
||||
json: { is_held: isHeld },
|
||||
});
|
||||
}
|
||||
|
||||
async serviceRebuild(repository: RepositoryId, packages: string[]): Promise<void> {
|
||||
return this.client.request("/api/v1/service/rebuild", {
|
||||
method: "POST",
|
||||
|
||||
@@ -130,6 +130,19 @@ export default function PackageInfoDialog({
|
||||
}
|
||||
};
|
||||
|
||||
const handleHoldToggle: () => Promise<void> = async () => {
|
||||
if (!localPackageBase || !currentRepository) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const newHeldStatus = !(status?.is_held ?? false);
|
||||
await client.service.servicePackageHoldUpdate(localPackageBase, currentRepository, newHeldStatus);
|
||||
void queryClient.invalidateQueries({ queryKey: QueryKeys.package(localPackageBase, currentRepository) });
|
||||
} catch (exception) {
|
||||
showError("Action failed", `Could not update hold status: ${ApiError.errorDetail(exception)}`);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeletePatch: (key: string) => Promise<void> = async key => {
|
||||
if (!localPackageBase) {
|
||||
return;
|
||||
@@ -189,6 +202,8 @@ export default function PackageInfoDialog({
|
||||
isAuthorized={isAuthorized}
|
||||
refreshDatabase={refreshDatabase}
|
||||
onRefreshDatabaseChange={setRefreshDatabase}
|
||||
isHeld={status?.is_held ?? false}
|
||||
onHoldToggle={() => void handleHoldToggle()}
|
||||
onUpdate={() => void handleUpdate()}
|
||||
onRemove={() => void handleRemove()}
|
||||
autoRefreshIntervals={autoRefreshIntervals}
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import PauseCircleIcon from "@mui/icons-material/PauseCircle";
|
||||
import PlayArrowIcon from "@mui/icons-material/PlayArrow";
|
||||
import PlayCircleIcon from "@mui/icons-material/PlayCircle";
|
||||
import { Button, Checkbox, DialogActions, FormControlLabel } from "@mui/material";
|
||||
import AutoRefreshControl from "components/common/AutoRefreshControl";
|
||||
import type { AutoRefreshInterval } from "models/AutoRefreshInterval";
|
||||
@@ -26,6 +28,8 @@ import type React from "react";
|
||||
|
||||
interface PackageInfoActionsProps {
|
||||
isAuthorized: boolean;
|
||||
isHeld: boolean;
|
||||
onHoldToggle: () => void;
|
||||
refreshDatabase: boolean;
|
||||
onRefreshDatabaseChange: (checked: boolean) => void;
|
||||
onUpdate: () => void;
|
||||
@@ -39,6 +43,8 @@ export default function PackageInfoActions({
|
||||
isAuthorized,
|
||||
refreshDatabase,
|
||||
onRefreshDatabaseChange,
|
||||
isHeld,
|
||||
onHoldToggle,
|
||||
onUpdate,
|
||||
onRemove,
|
||||
autoRefreshIntervals,
|
||||
@@ -52,6 +58,9 @@ export default function PackageInfoActions({
|
||||
control={<Checkbox checked={refreshDatabase} onChange={(_, checked) => onRefreshDatabaseChange(checked)} size="small" />}
|
||||
label="update pacman databases"
|
||||
/>
|
||||
<Button onClick={onHoldToggle} variant="outlined" color="warning" startIcon={isHeld ? <PlayCircleIcon /> : <PauseCircleIcon />} size="small">
|
||||
{isHeld ? "unhold" : "hold"}
|
||||
</Button>
|
||||
<Button onClick={onUpdate} variant="contained" color="success" startIcon={<PlayArrowIcon />} size="small">
|
||||
update
|
||||
</Button>
|
||||
|
||||
@@ -107,7 +107,8 @@ export default function PackageTable({ autoRefreshIntervals }: PackageTableProps
|
||||
width: 120,
|
||||
align: "center",
|
||||
headerAlign: "center",
|
||||
renderCell: (params: GridRenderCellParams<PackageRow>) => <StatusCell status={params.row.status} />,
|
||||
renderCell: (params: GridRenderCellParams<PackageRow>) =>
|
||||
<StatusCell status={params.row.status} isHeld={params.row.isHeld} />,
|
||||
},
|
||||
],
|
||||
[],
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import PauseCircleIcon from "@mui/icons-material/PauseCircle";
|
||||
import { Chip } from "@mui/material";
|
||||
import type { BuildStatus } from "models/BuildStatus";
|
||||
import type React from "react";
|
||||
@@ -24,10 +25,12 @@ import { StatusColors } from "theme/StatusColors";
|
||||
|
||||
interface StatusCellProps {
|
||||
status: BuildStatus;
|
||||
isHeld?: boolean;
|
||||
}
|
||||
|
||||
export default function StatusCell({ status }: StatusCellProps): React.JSX.Element {
|
||||
export default function StatusCell({ status, isHeld }: StatusCellProps): React.JSX.Element {
|
||||
return <Chip
|
||||
icon={isHeld ? <PauseCircleIcon /> : undefined}
|
||||
label={status}
|
||||
size="small"
|
||||
sx={{
|
||||
|
||||
@@ -32,6 +32,7 @@ export class PackageRow {
|
||||
timestamp: string;
|
||||
timestampValue: number;
|
||||
status: BuildStatus;
|
||||
isHeld: boolean;
|
||||
|
||||
constructor(descriptor: PackageStatus) {
|
||||
this.id = descriptor.package.base;
|
||||
@@ -45,6 +46,7 @@ export class PackageRow {
|
||||
this.timestamp = new Date(descriptor.status.timestamp * 1000).toISOStringShort();
|
||||
this.timestampValue = descriptor.status.timestamp;
|
||||
this.status = descriptor.status.status;
|
||||
this.isHeld = descriptor.status.is_held ?? false;
|
||||
}
|
||||
|
||||
private static extractListProperties(pkg: PackageStatus["package"], property: "groups" | "licenses"): string[] {
|
||||
|
||||
@@ -22,4 +22,5 @@ import type { BuildStatus } from "models/BuildStatus";
|
||||
export interface Status {
|
||||
status: BuildStatus;
|
||||
timestamp: number;
|
||||
is_held?: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user