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;
|