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

Bug 1870636: Add ability to select unassigned as application filter in topology #6343

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ interface ResourceDropdownProps {
allSelectorKey?: string;
allSelectorTitle?: string;
};
noneSelectorItem?: {
noneSelectorKey?: string;
noneSelectorTitle?: string;
};
actionItems?: {
actionTitle: string;
actionKey: string;
Expand Down Expand Up @@ -147,6 +151,7 @@ class ResourceDropdown extends React.Component<ResourceDropdownProps, State> {
dataSelector,
transformLabel,
allSelectorItem,
noneSelectorItem,
showBadge = false,
appendItems,
}: ResourceDropdownProps,
Expand Down Expand Up @@ -186,6 +191,9 @@ class ResourceDropdown extends React.Component<ResourceDropdownProps, State> {
if (allSelectorItem && !_.isEmpty(unsortedList)) {
sortedList[allSelectorItem.allSelectorKey] = allSelectorItem.allSelectorTitle;
}
if (noneSelectorItem && !_.isEmpty(unsortedList)) {
sortedList[noneSelectorItem.noneSelectorKey] = noneSelectorItem.noneSelectorTitle;
}

_.keys(unsortedList)
.sort()
Expand Down
1 change: 1 addition & 0 deletions frontend/packages/console-shared/src/constants/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const ALL_NAMESPACES_KEY = '#ALL_NS#';

// Use a key for the "all" applications option that would be an invalid application name to avoid a potential clash
export const ALL_APPLICATIONS_KEY = '#ALL_APPS#';
export const UNASSIGNED_APPLICATIONS_KEY = '#UNASSIGNED_APP#';

// Prefix our localStorage items to avoid conflicts if another app ever runs on the same domain.
export const STORAGE_PREFIX = 'bridge';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ interface ApplicationDropdownProps {
allSelectorKey?: string;
allSelectorTitle?: string;
};
noneSelectorItem?: {
noneSelectorKey?: string;
noneSelectorTitle?: string;
};
namespace?: string;
actionItems?: {
actionTitle: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { connect, Dispatch } from 'react-redux';
import {
ALL_NAMESPACES_KEY,
ALL_APPLICATIONS_KEY,
UNASSIGNED_APPLICATIONS_KEY,
APPLICATION_LOCAL_STORAGE_KEY,
} from '@console/shared';
import { setActiveApplication } from '@console/internal/actions/ui';
Expand All @@ -29,7 +30,13 @@ const ApplicationSelector: React.FC<Props> = ({ namespace, application, onChange
if (namespace === ALL_NAMESPACES_KEY) return null;

const allApplicationsTitle = 'all applications';
const title: string = application === ALL_APPLICATIONS_KEY ? allApplicationsTitle : application;
const noApplicationsTitle = 'unassigned';
const title: string =
application === ALL_APPLICATIONS_KEY
? allApplicationsTitle
: application === UNASSIGNED_APPLICATIONS_KEY
? noApplicationsTitle
: application;

const onApplicationChange = (newApplication: string, key: string) => {
key === ALL_APPLICATIONS_KEY ? onChange(key) : onChange(newApplication);
Expand All @@ -47,6 +54,10 @@ const ApplicationSelector: React.FC<Props> = ({ namespace, application, onChange
allSelectorKey: ALL_APPLICATIONS_KEY,
allSelectorTitle: allApplicationsTitle,
}}
noneSelectorItem={{
noneSelectorKey: UNASSIGNED_APPLICATIONS_KEY,
noneSelectorTitle: noApplicationsTitle,
}}
selectedKey={application || ALL_APPLICATIONS_KEY}
onChange={onApplicationChange}
storageKey={APPLICATION_LOCAL_STORAGE_KEY}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ export const gitImportInitialValues: GitImportFormData = {
export const externalImageValues: DeployImageFormData = {
formType: 'edit',
name: 'nationalparks-py',
application: { name: '', selectedKey: '#UNASSIGNED_KEY#' },
application: { name: '', selectedKey: UNASSIGNED_KEY },
project: { name: 'div' },
runtimeIcon: 'python',
route: {
Expand Down Expand Up @@ -520,7 +520,7 @@ export const externalImageValues: DeployImageFormData = {
export const internalImageValues: DeployImageFormData = {
formType: 'edit',
name: 'nationalparks-py',
application: { name: '', selectedKey: '#UNASSIGNED_KEY#' },
application: { name: '', selectedKey: UNASSIGNED_KEY },
project: { name: 'div' },
runtimeIcon: 'python',
route: {
Expand Down Expand Up @@ -618,7 +618,7 @@ export const knAppResources: AppResources = {
};

export const knExternalImageValues: DeployImageFormData = {
application: { name: '', selectedKey: '#UNASSIGNED_KEY#' },
application: { name: '', selectedKey: UNASSIGNED_KEY },
build: { env: [], strategy: '', triggers: {} },
deployment: { env: [], replicas: 1, triggers: { image: false } },
formType: 'edit',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ALL_APPLICATIONS_KEY } from '@console/shared';
import { useExtensions, Perspective, isPerspective } from '@console/plugin-sdk';
import { NormalizedBuilderImages, normalizeBuilderImages } from '../../utils/imagestream-utils';
import { doContextualBinding, sanitizeApplicationValue } from '../../utils/application-utils';
import { ALLOW_SERVICE_BINDING } from '../../const';
import { ALLOW_SERVICE_BINDING, UNASSIGNED_KEY } from '../../const';
import { GitImportFormData, FirehoseList, ImportData, Resources } from './import-types';
import { createOrUpdateResources, handleRedirect } from './import-submit-utils';
import { validationSchema } from './import-validation-utils';
Expand Down Expand Up @@ -53,7 +53,7 @@ const ImportForm: React.FC<ImportFormProps & StateProps> = ({
application: {
initial: sanitizeApplicationValue(activeApplication),
name: sanitizeApplicationValue(activeApplication),
selectedKey: activeApplication,
selectedKey: activeApplication === 'unassigned' ? UNASSIGNED_KEY : activeApplication,
},
git: {
url: '',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { GitImportFormData, Resources } from '../import-types';
import { healthChecksProbeInitialData } from '../../health-checks/health-checks-probe-utils';
import { UNASSIGNED_KEY } from '../../../const';

export const mockPipelineTemplate = {
apiVersion: 'tekton.dev/v1alpha1',
Expand Down Expand Up @@ -60,7 +61,7 @@ export const defaultData: GitImportFormData = {
application: {
initial: '',
name: '',
selectedKey: '#UNASSIGNED_KEY#',
selectedKey: UNASSIGNED_KEY,
},
name: 'nodejs-ex-git',
image: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const ApplicationSelector: React.FC<ApplicationSelectorProps> = ({
actionKey: CREATE_APPLICATION_KEY,
},
{
actionTitle: 'Unassigned',
actionTitle: 'unassigned',
actionKey: UNASSIGNED_KEY,
},
];
Expand All @@ -62,7 +62,7 @@ const ApplicationSelector: React.FC<ApplicationSelectorProps> = ({
label="Application"
helperTextInvalid={errorMessage}
validated={isValid ? 'default' : 'error'}
helperText="Select an application for your grouping or Unassigned to not use an application grouping."
helperText="Select an application for your grouping or unassigned to not use an application grouping."
>
<ApplicationDropdown
dropDownClassName="dropdown--full-width"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ class EditApplicationModal extends PromiseComponent<
> {
private handleSubmit = (values, actions) => {
const { resourceKind, resource } = this.props;
const application = _.get(values, 'application.name');
const applicationKey = values.application.selectedKey;
const application = applicationKey === UNASSIGNED_KEY ? undefined : values.application.name;

this.handlePromise(updateResourceApplication(resourceKind, resource, application))
.then(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as _ from 'lodash';
import { createAggregateEdges, Model, NodeModel } from '@patternfly/react-topology';
import { ALL_APPLICATIONS_KEY } from '@console/shared/src';
import { ALL_APPLICATIONS_KEY, UNASSIGNED_APPLICATIONS_KEY } from '@console/shared/src';
import { referenceFor } from '@console/internal/module/k8s';
import {
DEFAULT_SUPPORTED_FILTER_IDS,
Expand Down Expand Up @@ -112,7 +112,9 @@ export const updateModelFromFilters = (
if (application !== ALL_APPLICATIONS_KEY) {
dataModel.nodes.forEach((g) => {
const group = getApplicationGroupForNode(g, dataModel.nodes);
g.visible = g.visible && group?.label === application;
g.visible =
(g.visible && group?.label === application) ||
(!group && application === UNASSIGNED_APPLICATIONS_KEY);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class TopologyColaLayout extends ColaLayout {
initialRun: boolean,
addingNodes: boolean,
): void {
if (graph.getNodes()?.length === 0) {
if (graph.getNodes()?.filter((n) => n.isVisible()).length === 0) {
return;
}
super.startLayout(graph, initialRun, addingNodes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
GraphElement,
} from '@patternfly/react-topology';
import { DataList } from '@patternfly/react-core';
import { METRICS_POLL_INTERVAL, useDeepCompareMemoize } from '@console/shared';
import { METRICS_POLL_INTERVAL } from '@console/shared';
import { PROMETHEUS_TENANCY_BASE_PATH } from '@console/internal/components/graphs';
import {
fetchOverviewMetrics,
Expand Down Expand Up @@ -57,23 +57,14 @@ const ConnectedTopologyListView: React.FC<TopologyListViewProps &
updateMonitoringAlerts,
}) => {
const selectedId = selectedIds[0];
const [applicationGroups, setApplicationGroups] = React.useState<Node[]>();
const [unassignedItems, setUnassignedItems] = React.useState<Node[]>();

const nodes = useDeepCompareMemoize(
visualization.getElements().filter((e) => isNode(e)) as Node[],
const nodes = visualization.getElements().filter((e) => isNode(e)) as Node[];
const applicationGroups = nodes.filter((n) => n.getType() === TYPE_APPLICATION_GROUP);
applicationGroups.sort((a, b) => a.getLabel().localeCompare(b.getLabel()));
const unassignedItems = nodes.filter(
(n) => n.getType() !== TYPE_APPLICATION_GROUP && isGraph(n.getParent()) && n.isVisible(),
);

React.useEffect(() => {
const appGroups = nodes.filter((n) => n.getType() === TYPE_APPLICATION_GROUP);
appGroups.sort((a, b) => a.getLabel().localeCompare(b.getLabel()));
const items = nodes.filter(
(n) => n.getType() !== TYPE_APPLICATION_GROUP && isGraph(n.getParent()),
);
setApplicationGroups(appGroups);
setUnassignedItems(items);
}, [nodes]);

React.useEffect(() => {
if (selectedId) {
const element = document.getElementById(selectedId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const ObservedTopologyListViewUnassignedGroup: React.FC<TopologyListViewUnassign
className="odc-topology-list-view__application-label"
id="unassigned_label"
>
Unassigned
unassigned
</DataListCell>,
);
return (
Expand Down
2 changes: 1 addition & 1 deletion frontend/packages/dev-console/src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ export enum QUERY_PROPERTIES {
export const RESOURCE_NAME_TRUNCATE_LENGTH = 13;

export const CREATE_APPLICATION_KEY = '#CREATE_APPLICATION_KEY#';
export const UNASSIGNED_KEY = '#UNASSIGNED_KEY#';
export const UNASSIGNED_KEY = '#UNASSIGNED_APP#';
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const sanitizeApplicationValue = (
): string => {
switch (applicationType) {
case UNASSIGNED_KEY:
return 'unassigned';
case CREATE_APPLICATION_KEY:
return '';
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const getAppLabels = ({
if (runtimeIcon) {
labels['app.openshift.io/runtime'] = runtimeIcon;
}
if (applicationName && applicationName.trim().length > 0) {
if (applicationName && applicationName !== 'unassigned' && applicationName.trim().length > 0) {
labels['app.kubernetes.io/part-of'] = applicationName;
}
if (selectedTag) {
Expand Down