Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remember VM state filter settings #1035

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/components/aggregateStatusCards.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ export class AggregateStatusCards extends React.Component {
className='ct-card-info'
isSelectable
onKeyDown={event => this.onCardSelect(event, 'storages')}
onClick={() => cockpit.location.go(['storages'])}>
onClick={() => cockpit.location.go(['storages'], cockpit.location.options)}>
<CardHeader>
<Flex alignItems={{ default: 'alignItemsCenter' }}>
<ServerIcon size="md" />
<Button onClick={() => cockpit.location.go(['storages'])} variant="link">
<Button variant="link">
{cockpit.format(cockpit.ngettext("$0 Storage pool", "$0 Storage pools", this.props.storagePools.length), this.props.storagePools.length)}
</Button>
</Flex>
Expand All @@ -67,11 +67,11 @@ export class AggregateStatusCards extends React.Component {
className='ct-card-info'
isSelectable
onKeyDown={event => this.onCardSelect(event, 'networks')}
onClick={() => cockpit.location.go(['networks'])}>
onClick={() => cockpit.location.go(['networks'], cockpit.location.options)}>
<CardHeader>
<Flex alignItems={{ default: 'alignItemsCenter' }}>
<NetworkIcon size="md" />
<Button onClick={() => cockpit.location.go(['networks'])} variant="link">
<Button variant="link">
{cockpit.format(cockpit.ngettext("$0 Network", "$0 Networks", this.props.networks.length), this.props.networks.length)}
</Button>
</Flex>
Expand Down
2 changes: 1 addition & 1 deletion src/components/networks/networkList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class NetworkList extends React.Component {
<Page>
<PageBreadcrumb stickyOnBreakpoint={{ default: "top" }}>
<Breadcrumb variant={PageSectionVariants.light} className='machines-listing-breadcrumb'>
<BreadcrumbItem to='#'>
<BreadcrumbItem to={'#' + cockpit.location.encode('/', cockpit.location.options.status ? { status: cockpit.location.options.status } : {})}>
{_("Virtual machines")}
</BreadcrumbItem>
<BreadcrumbItem isActive>
Expand Down
2 changes: 1 addition & 1 deletion src/components/storagePools/storagePoolList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class StoragePoolList extends React.Component {
<Page>
<PageBreadcrumb stickyOnBreakpoint={{ default: "top" }}>
<Breadcrumb className='machines-listing-breadcrumb'>
<BreadcrumbItem to='#'>
<BreadcrumbItem to={'#' + cockpit.location.encode('/', cockpit.location.options.status ? { status: cockpit.location.options.status } : {})}>
{_("Virtual machines")}
</BreadcrumbItem>
<BreadcrumbItem isActive>
Expand Down
2 changes: 1 addition & 1 deletion src/components/vm/vmDetailsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ export const VmDetailsPage = ({
<PageGroup>
<PageBreadcrumb>
<Breadcrumb className='machines-listing-breadcrumb'>
<BreadcrumbItem to='#'>
<BreadcrumbItem to={'#' + cockpit.location.encode('/', cockpit.location.options.status ? { status: cockpit.location.options.status } : {})}>
{_("Virtual machines")}
</BreadcrumbItem>
<BreadcrumbItem isActive>
Expand Down
36 changes: 32 additions & 4 deletions src/components/vms/hostvmslist.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
*/
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import cockpit from 'cockpit';

Expand All @@ -29,6 +29,7 @@ import { Toolbar, ToolbarContent, ToolbarItem } from "@patternfly/react-core/dis
import { Select, SelectOption } from "@patternfly/react-core/dist/esm/deprecated/components/Select";
import { Page, PageSection } from "@patternfly/react-core/dist/esm/components/Page";
import { WithDialogs } from 'dialogs.jsx';
import { usePageLocation } from 'hooks';

import VmActions from '../vm/vmActions.jsx';
import { updateVm } from '../../actions/store-actions.js';
Expand Down Expand Up @@ -65,11 +66,22 @@ const VmState = ({ vm, dismissError }) => {

const _ = cockpit.gettext;

function getStatusFilterOption(options) {
if (!options.status) {
const defaultSelection = { value: _("All"), toString: function() { return this.value } };
return defaultSelection;
}

return { value: rephraseUI('resourceStates', options.status), apiState: options.status, toString: function() { return this.value } };
}

/**
* List of all VMs defined on this host
*/
const HostVmsList = ({ vms, config, ui, storagePools, actions, networks, onAddErrorNotification }) => {
const [statusSelected, setStatusSelected] = useState({ value: _("All"), toString: function() { return this.value } });
const { options } = usePageLocation();

const [statusSelected, setStatusSelected] = useState(getStatusFilterOption(options));
const [currentTextFilter, setCurrentTextFilter] = useState("");
const [statusIsExpanded, setStatusIsExpanded] = useState(false);
const combinedVms = [...vms, ...dummyVmsFilter(vms, ui.vms)];
Expand All @@ -92,6 +104,19 @@ const HostVmsList = ({ vms, config, ui, storagePools, actions, networks, onAddEr
.map(state => { return { value: rephraseUI('resourceStates', state), apiState: state } })
.sort((a, b) => (prioritySorting[a.apiState] || 0) - (prioritySorting[b.apiState] || 0) || a.value.localeCompare(b.value)));

useEffect(() => {
setStatusSelected(getStatusFilterOption(options));
}, [options]);

const onStatusFilterChange = (selection) => {
if (selection.value === _("All")) {
delete options.status;
cockpit.location.go([], { ...options });
} else {
cockpit.location.go([], { ...options, status: selection.apiState });
}
};

const toolBar = (
<Toolbar>
<ToolbarContent>
Expand All @@ -109,7 +134,10 @@ const HostVmsList = ({ vms, config, ui, storagePools, actions, networks, onAddEr
<Select variant="single"
toggleId="vm-state-select-toggle"
onToggle={(_event, statusIsExpanded) => setStatusIsExpanded(statusIsExpanded)}
onSelect={(event, selection) => { setStatusIsExpanded(false); setStatusSelected(selection) }}
onSelect={(event, selection) => {
setStatusIsExpanded(false);
onStatusFilterChange(selection);
}}
selections={statusSelected}
isOpen={statusIsExpanded}
aria-labelledby="vm-state-select">
Expand Down Expand Up @@ -167,7 +195,7 @@ const HostVmsList = ({ vms, config, ui, storagePools, actions, networks, onAddEr
isInline
isDisabled={vm.isUi && !vm.createInProgress}
component="a"
href={'#' + cockpit.format("vm?name=$0&connection=$1", encodeURIComponent(vm.name), vm.connectionName)}
href={'#' + cockpit.format(`vm?name=$0&connection=$1${options.status ? '&status=$2' : ''}`, encodeURIComponent(vm.name), vm.connectionName, options.status)}
className="vm-list-item-name">{vm.name}</Button>
},
{ title: rephraseUI('connections', vm.connectionName) },
Expand Down
30 changes: 30 additions & 0 deletions test/check-machines-lifecycle
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,36 @@ class TestMachinesLifecycle(VirtualMachinesCase):
b.wait_in_text(".pf-c-popover", "VM subVmTest2 failed to start")
b.click('#vm-subVmTest2-system-state button[aria-label=Close]')

def testVmFilterSettingsOnNavigate(self):
KKoukiou marked this conversation as resolved.
Show resolved Hide resolved
b = self.browser

self.createVm("subVmTest1")
self.createVm("subVmTest2", running=False)

self.login_and_go("/machines")
self.waitPageInit()

b.select_PF4("#vm-state-select-toggle", "Running")
b.wait(lambda: "status=running" in b.eval_js("window.location.href"))
b.reload()
b.enter_page("/machines")
b.wait_in_text("#vm-state-select-toggle .pf-c-select__toggle-text", "Running")

self.goToVmPage("subVmTest1")
b.wait(lambda: "vm?name=subVmTest1&connection=system&status=running" in b.eval_js("window.location.href"))
self.goToMainPage()
b.wait(lambda: "status=running" in b.eval_js("window.location.href"))

b.click("#card-pf-storage-pools")
b.wait(lambda: "storages?status=running" in b.eval_js("window.location.href"))
self.goToMainPage()
b.wait(lambda: "status=running" in b.eval_js("window.location.href"))

b.click("#card-pf-networks")
b.wait(lambda: "networks?status=running" in b.eval_js("window.location.href"))
self.goToMainPage()
b.wait(lambda: "status=running" in b.eval_js("window.location.href"))

def testCloneSessionConnection(self):
self.testClone(connectionName='session')

Expand Down