LCOV - code coverage report
Current view: top level - src - PruneUnusedContainersModal.jsx Coverage Total Hit
Test: cockpit-podman Lines: 79.8 % 84 67
Test Date: 2025-05-21 17:35:03

            Line data    Source code
       1           43 : import React, { useState } from 'react';
       2              : 
       3              : import { Button } from "@patternfly/react-core/dist/esm/components/Button";
       4              : import {
       5              :     Modal
       6              : } from '@patternfly/react-core/dist/esm/deprecated/components/Modal';
       7              : import { SortByDirection } from "@patternfly/react-table";
       8              : 
       9              : import cockpit from 'cockpit';
      10              : import { ListingTable } from 'cockpit-components-table';
      11              : 
      12              : import * as client from './client.js';
      13              : import { RelativeTime } from './util.js';
      14              : 
      15           43 : const _ = cockpit.gettext;
      16              : 
      17            2 : const getContainerRow = (container, showOwnerColumn, users, selected) => {
      18            2 :     const columns = [
      19            2 :         {
      20            2 :             title: container.name,
      21            2 :             sortKey: container.name,
      22            2 :             props: { width: 25, },
      23            2 :         },
      24            2 :         {
      25            2 :             title: <RelativeTime time={container.created} />,
      26            2 :             props: { width: 20, },
      27            2 :         },
      28            2 :     ];
      29              : 
      30            2 :     const username = users.find(u => u.uid === container.uid)?.name;
      31              : 
      32            2 :     if (showOwnerColumn)
      33            2 :         columns.push({
      34            1 :             title: container.uid === 0 ? _("system") : <div><span className="ct-grey-text">{_("user:")} </span>{username}</div>,
      35            2 :             sortKey: container.key,
      36            2 :             props: {
      37            2 :                 className: "ignore-pixels",
      38            2 :                 modifier: "nowrap"
      39            2 :             }
      40            2 :         });
      41              : 
      42            2 :     return { columns, selected, props: { key: container.key } };
      43            2 : };
      44              : 
      45            2 : const PruneUnusedContainersModal = ({ close, unusedContainers, onAddNotification, users }) => {
      46            2 :     const [isPruning, setPruning] = useState(false);
      47            2 :     const [selectedContainerKeys, setSelectedContainerKeys] = React.useState(unusedContainers.map(u => u.key));
      48              : 
      49            2 :     const handlePruneUnusedContainers = () => {
      50            2 :         setPruning(true);
      51              : 
      52            2 :         const con_for = uid => users.find(u => u.uid === uid).con;
      53              : 
      54            2 :         const actions = unusedContainers
      55            2 :                 .filter(u => selectedContainerKeys.includes(u.key))
      56            2 :                 .map(u => client.delContainer(con_for(u.uid), u.id, true));
      57              : 
      58            2 :         Promise.all(actions).then(close)
      59            0 :                 .catch(ex => {
      60            0 :                     const error = _("Failed to prune unused containers");
      61            0 :                     onAddNotification({ type: 'danger', error, errorDetail: ex.message });
      62            0 :                     close();
      63            0 :                 });
      64            2 :     };
      65              : 
      66            2 :     const columns = [
      67            2 :         { title: _("Name"), sortable: true },
      68            2 :         { title: _("Created"), sortable: true },
      69            2 :     ];
      70              : 
      71            2 :     const showOwnerColumn = unusedContainers.some(u => u.uid !== 0);
      72              : 
      73            2 :     if (showOwnerColumn)
      74            2 :         columns.push({ title: _("Owner"), sortable: true });
      75              : 
      76            0 :     const selectAllContainers = isSelecting => setSelectedContainerKeys(isSelecting ? unusedContainers.map(c => c.key) : []);
      77            2 :     const isContainerSelected = container => selectedContainerKeys.includes(container.key);
      78            0 :     const setContainerSelected = (container, isSelecting) => setSelectedContainerKeys(prevSelected => {
      79            0 :         const otherSelectedContainerNames = prevSelected.filter(r => r !== container.key);
      80            0 :         return isSelecting ? [...otherSelectedContainerNames, container.key] : otherSelectedContainerNames;
      81            0 :     });
      82              : 
      83            0 :     const onSelectContainer = (key, _rowIndex, isSelecting) => {
      84            0 :         const container = unusedContainers.find(u => u.key === key);
      85            0 :         setContainerSelected(container, isSelecting);
      86            0 :     };
      87              : 
      88            2 :     return (
      89            2 :         <Modal isOpen
      90            2 :                onClose={close}
      91            2 :                position="top" variant="medium"
      92            2 :                title={cockpit.format(_("Prune unused containers"))}
      93            2 :                footer={<>
      94            2 :                    <Button id="btn-img-delete" variant="danger"
      95            2 :                            spinnerAriaValueText={isPruning ? _("Pruning containers") : undefined}
      96            2 :                            isLoading={isPruning}
      97            2 :                            isDisabled={isPruning || selectedContainerKeys.length === 0}
      98            2 :                            onClick={handlePruneUnusedContainers}>
      99            2 :                        {isPruning ? _("Pruning containers") : _("Prune")}
     100            2 :                    </Button>
     101            0 :                    <Button variant="link" onClick={() => close()}>{_("Cancel")}</Button>
     102            2 :                </>}
     103              :         >
     104            2 :             <p>{_("Removes selected non-running containers")}</p>
     105            2 :             <ListingTable columns={columns}
     106            0 :                           onSelect={(_event, isSelecting, rowIndex, rowData) => onSelectContainer(rowData.props.id, rowIndex, isSelecting)}
     107            0 :                           onHeaderSelect={(_event, isSelecting) => selectAllContainers(isSelecting)}
     108            2 :                           id="unused-container-list"
     109            2 :                           rows={unusedContainers.map(container => getContainerRow(container, showOwnerColumn, users, isContainerSelected(container))) }
     110            2 :                           variant="compact" sortBy={{ index: 0, direction: SortByDirection.asc }} />
     111            2 :         </Modal>
     112              :     );
     113            2 : };
     114              : 
     115           43 : export default PruneUnusedContainersModal;
        

Generated by: LCOV version 2.0-1