Skip to content

Commit

Permalink
Convert Providers screen to Console convention
Browse files Browse the repository at this point in the history
Reference-Url: oVirt/ovirt-web-ui#1600
Reference-Url: oVirt/ovirt-web-ui#1592
  • Loading branch information
rszwajko committed Aug 31, 2022
1 parent 56a2e46 commit 88dd791
Show file tree
Hide file tree
Showing 9 changed files with 594 additions and 5 deletions.
32 changes: 31 additions & 1 deletion console-extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,36 @@
"insertAfter": "workloads"
}
},
{
"type": "console.navigation/resource-ns",
"properties": {
"id": "providers",
"section": "migrationtoolkit",
"name": "%plugin__forklift-console-plugin~Providers%",
"model": {
"group": "forklift.konveyor.io",
"kind": "Provider",
"version": "v1beta1"
},
"dataAttributes": {
"data-quickstart-id": "qs-nav-providers",
"data-test-id": "providers-nav-item"
}
}
},
{
"type": "console.page/resource/list",
"properties": {
"component": {
"$codeRef": "ProvidersRes"
},
"model": {
"group": "forklift.konveyor.io",
"kind": "Provider",
"version": "v1beta1"
}
}
},
{
"type": "console.navigation/href",
"properties": {
Expand Down Expand Up @@ -113,4 +143,4 @@
"exact": true
}
}
]
]
11 changes: 9 additions & 2 deletions locales/en/plugin__forklift-console-plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
{
"AddProvider": "Add Provider",
"Any": "Any",
"Migration Toolkit": "Migration Toolkit",
"Name": "Name",
"NetworkMaps": "NetworkMaps",
"Plans": "Plans",
"Providers": "Providers",
"StorageMaps": "StorageMaps"
}
"SelectFilter": "Select Filter",
"StorageMaps": "StorageMaps",
"Status": "Status",
"Type": "Type",
"Url": "Endpoint"
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,11 @@
"MappingsPage": "./extensions/MappingsWrapper",
"HostsPage": "./extensions/HostsPageWrapper",
"PlanWizard": "./extensions/PlanWizardWrapper",
"VMMigrationDetails": "./extensions/VMMigrationDetailsWrapper"
"VMMigrationDetails": "./extensions/VMMigrationDetailsWrapper",
"ProvidersRes": "./Providers/ProvidersPage"
},
"dependencies": {
"@console/pluginAPI": "*"
}
}
}
}
148 changes: 148 additions & 0 deletions src/Providers/ProvidersPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React, { useState } from 'react';
import { useTranslation } from 'src/internal/i18n';
import { ProviderResource } from 'src/internal/k8s';

import { MOCK_CLUSTER_PROVIDERS } from '@app/queries/mocks/providers.mock';
import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk';
import {
Button,
Level,
LevelItem,
PageSection,
Title,
Toolbar,
ToolbarContent,
} from '@patternfly/react-core';

import Filters from './components/Filters';
import ProvidersTableView from './components/ProvidersTableView';
import { Field } from './components/shared';
import { NAME, STATUS, TYPE, URL } from './components/shared';

const isMock = process.env.DATA_SOURCE === 'mock';

const useProviders = ({ kind, namespace }) => {
const [providers, loaded, error] = isMock
? [MOCK_CLUSTER_PROVIDERS, true, false]
: useK8sWatchResource<ProviderResource[]>({
kind,
isList: true,
namespaced: true,
namespace,
});

// const inventoryProvidersQuery = useInventoryProvidersQuery();
// providers.map(p => enhanceWithInventory(inventoryProvidersQuery))

// const allErrorTitles = [
// 'Cannot load providers from cluster API',
// 'Cannot load providers from inventory API',
// ];

return [providers, loaded, error];
};

const fields: Field[] = [
{
id: NAME,
tKey: 'plugin__forklift-console-plugin~Name',
filter: {
type: 'freetext',
placeholderKey: 'plugin__forklift-console-plugin~Any',
},
sortable: true,
from: (provider) => provider?.metadata?.name ?? '',
},
{
id: STATUS,
tKey: 'plugin__forklift-console-plugin~Status',
filter: {
type: 'enum',
placeholderKey: 'plugin__forklift-console-plugin~Any',
values: [{ id: '', tKey: '' }],
},
sortable: true,
from: (provider) => provider?.status?.conditions?.[0]?.type ?? '',
},
{
id: URL,
tKey: 'plugin__forklift-console-plugin~Url',
filter: {
type: 'freetext',
placeholderKey: 'plugin__forklift-console-plugin~Any',
},
sortable: true,
from: (provider) => provider?.spec?.url ?? '',
},
{
id: TYPE,
tKey: 'plugin__forklift-console-plugin~Type',
filter: {
type: 'enum',
placeholderKey: 'plugin__forklift-console-plugin~Any',
values: [{ id: '', tKey: '' }],
},
sortable: true,
from: (provider) => provider?.spec?.type ?? '',
},
];

export const ProvidersPage: React.FunctionComponent<ProvidersPageProps> = ({
namespace,
kind,
}) => {
const { t } = useTranslation();
const [providers, loaded, error] = useProviders({ kind, namespace });
const [selectedFilters, setSelectedFilters] = useState([]);

console.error('Providers', providers, loaded, error, fields);

return (
<>
<PageSection variant="light">
<Level>
<LevelItem>
<Title headingLevel="h1">{t('Providers')}</Title>
</LevelItem>
<LevelItem>
<Button variant="primary" onClick={() => ''}>
{t('AddProvider')}
</Button>
</LevelItem>
</Level>
</PageSection>
<PageSection>
<Toolbar clearAllFilters={() => setSelectedFilters([])}>
<ToolbarContent>
<Filters
filterTypes={fields.map(({ id, tKey, filter }) => ({
id,
tKey,
filter,
}))}
onFilterUpdate={setSelectedFilters}
selectedFilters={selectedFilters}
/>
</ToolbarContent>
</Toolbar>

{loaded && error && <Errors />}
{!loaded && <Loading />}
{loaded && !error && (
<ProvidersTableView providers={providers} fields={fields} />
)}
</PageSection>
</>
);
};

const Errors = () => <> Erorrs!</>;

const Loading = () => <> Loading!</>;

type ProvidersPageProps = {
kind: string;
namespace: string;
};

export default ProvidersPage;
104 changes: 104 additions & 0 deletions src/Providers/components/Filters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React, { useState } from 'react';
import { useTranslation } from 'src/internal/i18n';

import {
Select,
SelectOption,
SelectOptionObject,
SelectVariant,
ToolbarGroup,
ToolbarItem,
ToolbarToggleGroup,
} from '@patternfly/react-core';
import { FilterIcon } from '@patternfly/react-icons/dist/esm/icons';

import FreetextFilter from './FreetextFilter';
import { EnumFilterDef, FreetextFilterDef } from './shared';

interface IdOption extends SelectOptionObject {
id: string;
}

const toSelectOption = (id: string, label: string): IdOption => ({
id,
compareTo: (other: IdOption): boolean => id === other?.id,
toString: () => label,
});

const Filters: React.FunctionComponent<FiltersProps> = ({
selectedFilters,
onFilterUpdate,
filterTypes,
}) => {
const { t } = useTranslation();
const [currentFilterType, setCurrentFilterType] = useState(filterTypes[0]);
const [expanded, setExpanded] = useState(false);

// const nameFilter = filterTypes.find(({ id }) => id === textBasedFilterId);
const selectOptionToFilter = (selectedId) =>
filterTypes.find(({ id }) => id === selectedId) ?? currentFilterType;

const onFilterTypeSelect = (event, value, isPlaceholder) => {
if (!isPlaceholder) {
setCurrentFilterType(selectOptionToFilter(value?.id));
setExpanded(!expanded);
}
};

return (
<ToolbarToggleGroup toggleIcon={<FilterIcon />} breakpoint="xl">
<ToolbarGroup variant="filter-group">
<ToolbarItem>
<Select
onSelect={onFilterTypeSelect}
onToggle={setExpanded}
isOpen={expanded}
toggleIcon={<FilterIcon />}
variant={SelectVariant.single}
aria-label={t('SelectFilter')}
selections={toSelectOption(
currentFilterType.id,
t(currentFilterType.tKey),
)}
>
{filterTypes.map(({ id, tKey }) => (
<SelectOption key={id} value={toSelectOption(id, t(tKey))} />
))}
</Select>
</ToolbarItem>

{filterTypes.map(
({ id, tKey: fieldKey, filter: { type, tKey, placeholderKey } }) => {
switch (type) {
case 'freetext':
return (
<FreetextFilter
filterId={id}
onFilterUpdate={onFilterUpdate}
placeholderLabel={t(placeholderKey)}
selectedFilters={selectedFilters}
showFilter={currentFilterType?.id === id}
title={t(tKey ?? fieldKey)}
/>
);
// case 'enum':
// return <>enum</>;
}
},
)}
</ToolbarGroup>
</ToolbarToggleGroup>
);
};

interface FiltersProps {
selectedFilters: any[];
filterTypes: {
id: string;
tKey: string;
filter: EnumFilterDef | FreetextFilterDef;
}[];
onFilterUpdate(filter: any): void;
}

export default Filters;
Loading

0 comments on commit 88dd791

Please sign in to comment.