Line data Source code
1 : /*
2 : * Copyright (C) 2021 Red Hat, Inc.
3 : * SPDX-License-Identifier: LGPL-2.1-or-later
4 : */
5 :
6 123 : import cockpit from "cockpit";
7 :
8 123 : import React, { useState } from "react";
9 : import { ListingTable } from "cockpit-components-table.jsx";
10 : import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
11 : import { Label } from "@patternfly/react-core/dist/esm/components/Label/index.js";
12 : import { Split, SplitItem } from "@patternfly/react-core/dist/esm/layouts/Split/index.js";
13 : import {
14 : Modal,
15 : ModalBody,
16 : ModalFooter,
17 : ModalHeader
18 : } from '@patternfly/react-core/dist/esm/components/Modal/index.js';
19 : import { useInit } from "hooks";
20 : import { DialogResult } from "dialogs";
21 :
22 : import { ShellState } from "./state";
23 :
24 123 : const _ = cockpit.gettext;
25 :
26 : export interface ActivePagesDialogProps {
27 : dialogResult: DialogResult<void>;
28 : state: ShellState;
29 : }
30 :
31 0 : export const ActivePagesDialog = ({
32 0 : dialogResult,
33 0 : state
34 0 : }: ActivePagesDialogProps) => {
35 0 : function get_pages() {
36 0 : const result = [];
37 0 : for (const frame of Object.values(state.frames)) {
38 0 : if (frame.url) {
39 0 : const active = (frame == state.current_frame ||
40 0 : state.most_recent_path_for_host(frame.host) == frame.path);
41 0 : result.push({
42 0 : frame,
43 0 : active,
44 0 : selected: active,
45 0 : displayName: frame.host === "localhost" ? "/" + frame.path : frame.host + ":/" + frame.path,
46 0 : });
47 0 : }
48 0 : }
49 :
50 : // sort the frames by displayName, active ones first
51 0 : result.sort(function(a, b) {
52 0 : return (a.active ? -2 : 0) + (b.active ? 2 : 0) +
53 0 : ((a.displayName < b.displayName) ? -1 : 0) + ((b.displayName < a.displayName) ? 1 : 0);
54 0 : });
55 :
56 0 : return result;
57 0 : }
58 :
59 0 : const init_pages = useInit(get_pages, [frames]);
60 0 : const [pages, setPages] = useState(init_pages);
61 :
62 0 : function onRemove() {
63 0 : pages.forEach(element => {
64 0 : if (element.selected) {
65 0 : state.remove_frame(element.frame.name);
66 0 : }
67 0 : });
68 0 : dialogResult.resolve();
69 0 : }
70 :
71 0 : const rows = pages.map(page => {
72 0 : const columns = [{
73 0 : title: <Split>
74 0 : <SplitItem isFilled>
75 0 : {page.displayName}
76 0 : </SplitItem>
77 0 : <SplitItem>
78 0 : {page.active && <Label color="blue">{_("active")}</Label>}
79 0 : </SplitItem>
80 0 : </Split>,
81 0 : }];
82 0 : return ({
83 0 : props: {
84 0 : key: page.frame.name,
85 0 : 'data-row-id': page.frame.name
86 0 : },
87 0 : columns,
88 0 : selected: page.selected,
89 0 : });
90 0 : });
91 :
92 0 : return (
93 0 : <Modal isOpen position="top" variant="small"
94 0 : id="active-pages-dialog"
95 0 : onClose={() => dialogResult.resolve()}
96 : >
97 0 : <ModalHeader title={_("Active pages")} />
98 0 : <ModalBody>
99 0 : <ListingTable showHeader={false}
100 0 : columns={[{ title: _("Page name") }]}
101 0 : aria-label={_("Active pages")}
102 0 : emptyCaption={ _("There are currently no active pages") }
103 0 : onSelect={(_event, isSelected, rowIndex) => {
104 0 : const new_pages = [...pages];
105 0 : new_pages[rowIndex].selected = isSelected;
106 0 : setPages(new_pages);
107 0 : }}
108 0 : rows={rows} />
109 0 : </ModalBody>
110 0 : <ModalFooter>
111 0 : <Button variant='primary' onClick={onRemove}>{_("Close selected pages")}</Button>
112 0 : <Button variant='link' onClick={() => dialogResult.resolve()}>{_("Cancel")}</Button>
113 0 : </ModalFooter>
114 0 : </Modal>
115 : );
116 0 : };
|