Skip to content

[core] Refactor frontend code of plugins #238

New issue

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

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

Already on GitHub? # to your account

Merged
merged 5 commits into from
Dec 17, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan
- [#233](https://github.com/kobsio/kobs/pull/233): [resources] Highlight expanded row for containers in Pod details.
- [#235](https://github.com/kobsio/kobs/pull/235): [resources] Use `TableComposable` instead of `Table` component and unify table style across plugins.
- [#237](https://github.com/kobsio/kobs/pull/237): [core] Adjust API paths to use the same schema as the Azure plugin.
- [#239](https://github.com/kobsio/kobs/pull/239): [azure] Cost Management drill-down on resourceGroups.
- [#239](https://github.com/kobsio/kobs/pull/239): [azure] Cost Management drill-down on resource groups.
- [#238](https://github.com/kobsio/kobs/pull/238): [core] Refactor frontend code for plugins (change options handling, use `setDetails` instead of `showDetails` and rename plugins options in panels to `pluginOptions`).

## [v0.7.0](https://github.com/kobsio/kobs/releases/tag/v0.7.0) (2021-11-19)

Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/develop-a-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ export interface IPluginPanelProps {
description?: string;
pluginOptions?: IPluginDataOptions;
options?: any;
showDetails?: (details: React.ReactNode) => void;
setDetails?: (details: React.ReactNode) => void;
}
```

Expand Down
2 changes: 1 addition & 1 deletion plugins/applications/src/components/page/Application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ const Application: React.FunctionComponent = () => {
<DrawerContent panelContent={details}>
<DrawerContentBody>
{data.dashboards ? (
<DashboardsWrapper defaults={data} references={data.dashboards} showDetails={setDetails} />
<DashboardsWrapper defaults={data} references={data.dashboards} setDetails={setDetails} />
) : (
<PageSection style={{ minHeight: '100%' }} variant={PageSectionVariants.default}></PageSection>
)}
Expand Down
22 changes: 14 additions & 8 deletions plugins/applications/src/components/page/Applications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
PageSectionVariants,
Title,
} from '@patternfly/react-core';
import React, { useMemo, useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';

import ApplicationsToolbar from './ApplicationsToolbar';
Expand All @@ -32,8 +32,8 @@ const Applications: React.FunctionComponent<IApplicationsProps> = ({
}: IApplicationsProps) => {
const history = useHistory();
const location = useLocation();
const [options, setOptions] = useState<IOptions>(useMemo<IOptions>(() => getInitialOptions(), []));
const [selectedApplication, setSelectedApplication] = useState<React.ReactNode>(undefined);
const [options, setOptions] = useState<IOptions>();
const [details, setDetails] = useState<React.ReactNode>(undefined);

// changeOptions is used to change the options. Besides setting a new value for the options state we also reflect the
// options in the current url.
Expand All @@ -45,10 +45,16 @@ const Applications: React.FunctionComponent<IApplicationsProps> = ({
pathname: location.pathname,
search: `?view=${opts.view}${c.length > 0 ? c.join('') : ''}${n.length > 0 ? n.join('') : ''}`,
});

setOptions(opts);
};

useEffect(() => {
setOptions((prevOptions) => getInitialOptions(location.search, !prevOptions));
}, [location.search]);

if (!options) {
return null;
}

return (
<React.Fragment>
<PageSection variant={PageSectionVariants.light}>
Expand All @@ -59,8 +65,8 @@ const Applications: React.FunctionComponent<IApplicationsProps> = ({
<ApplicationsToolbar options={options} setOptions={changeOptions} />
</PageSection>

<Drawer isExpanded={selectedApplication !== undefined}>
<DrawerContent panelContent={selectedApplication}>
<Drawer isExpanded={details !== undefined}>
<DrawerContent panelContent={details}>
<DrawerContentBody>
<PageSection
style={options.view === 'topology' ? { height: '100%', minHeight: '100%' } : { minHeight: '100%' }}
Expand All @@ -82,7 +88,7 @@ const Applications: React.FunctionComponent<IApplicationsProps> = ({
view: options.view,
}}
times={options.times}
showDetails={setSelectedApplication}
setDetails={setDetails}
/>
)}
</PageSection>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface IApplicationsTopologyProps {
clusters: string[];
namespaces: string[];
times: IPluginTimes;
showDetails?: (details: React.ReactNode) => void;
setDetails?: (details: React.ReactNode) => void;
}

// ApplicationsTopology is the component to display all applications inside a topology view. We need a list of clusters
Expand All @@ -26,7 +26,7 @@ const ApplicationsTopology: React.FunctionComponent<IApplicationsTopologyProps>
clusters,
namespaces,
times,
showDetails,
setDetails,
}: IApplicationsTopologyProps) => {
const history = useHistory();

Expand Down Expand Up @@ -93,7 +93,7 @@ const ApplicationsTopology: React.FunctionComponent<IApplicationsTopologyProps>

return (
<div style={{ height: '100%', minHeight: '100%' }}>
<ApplicationsTopologyGraph edges={data.edges} nodes={data.nodes} showDetails={showDetails} />
<ApplicationsTopologyGraph edges={data.edges} nodes={data.nodes} setDetails={setDetails} />
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,14 @@ const nodeLabel = (node: INodeData): string => {
interface IApplicationsTopologyGraphProps {
edges: IEdge[];
nodes: INode[];
showDetails?: (details: React.ReactNode) => void;
setDetails?: (details: React.ReactNode) => void;
}

// ApplicationsTopologyGraph is the component, which renders the topology graph.
const ApplicationsTopologyGraph: React.FunctionComponent<IApplicationsTopologyGraphProps> = ({
edges,
nodes,
showDetails,
setDetails,
}: IApplicationsTopologyGraphProps) => {
const [width, setWidth] = useState<number>(0);
const [height, setHeight] = useState<number>(0);
Expand All @@ -115,11 +115,11 @@ const ApplicationsTopologyGraph: React.FunctionComponent<IApplicationsTopologyGr
const node = event.target;
const data: INodeData = node.data();

if (data.type === 'application' && showDetails) {
showDetails(<Details application={data} close={(): void => showDetails(undefined)} />);
if (data.type === 'application' && setDetails) {
setDetails(<Details application={data} close={(): void => setDetails(undefined)} />);
}
},
[showDetails],
[setDetails],
);

const cyCallback = useCallback(
Expand Down
4 changes: 2 additions & 2 deletions plugins/applications/src/components/panel/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const Panel: React.FunctionComponent<IPanelProps> = ({
description,
options,
times,
showDetails,
setDetails,
}: IPanelProps) => {
// We have to validate that the required options object was provided in the Application CR by a user. This is
// important so that the React UI doesn't crash, when the user didn't use the plugin correctly.
Expand All @@ -44,7 +44,7 @@ export const Panel: React.FunctionComponent<IPanelProps> = ({
clusters={options.clusters || [defaults.cluster]}
namespaces={options.namespaces || [defaults.namespace]}
times={times}
showDetails={showDetails}
setDetails={setDetails}
/>
);

Expand Down
6 changes: 3 additions & 3 deletions plugins/applications/src/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { IOptions, TView } from './interfaces';
import { getTimeParams } from '@kobsio/plugin-core';

// getInitialOptions returns the initial options for the applications page from the url.
export const getInitialOptions = (): IOptions => {
const params = new URLSearchParams(window.location.search);
export const getInitialOptions = (search: string, isInitial: boolean): IOptions => {
const params = new URLSearchParams(search);
const clusters = params.getAll('cluster');
const namespaces = params.getAll('namespace');
const view = params.get('view');

return {
clusters: clusters,
namespaces: namespaces,
times: getTimeParams(params),
times: getTimeParams(params, isInitial),
view: view ? (view as TView) : 'gallery',
};
};
8 changes: 4 additions & 4 deletions plugins/azure/src/components/panel/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const Panel: React.FunctionComponent<IPanelProps> = ({
description,
times,
options,
showDetails,
setDetails,
}: IPanelProps) => {
// Panels for container services.
if (
Expand All @@ -48,7 +48,7 @@ export const Panel: React.FunctionComponent<IPanelProps> = ({
<CIContainerGroups
name={name}
resourceGroups={options.containerinstances.resourceGroups}
setDetails={showDetails}
setDetails={setDetails}
/>
</PluginCard>
);
Expand Down Expand Up @@ -143,7 +143,7 @@ export const Panel: React.FunctionComponent<IPanelProps> = ({
<KSKubernetesServices
name={name}
resourceGroups={options.kubernetesservices.resourceGroups}
setDetails={showDetails}
setDetails={setDetails}
/>
</PluginCard>
);
Expand Down Expand Up @@ -225,7 +225,7 @@ export const Panel: React.FunctionComponent<IPanelProps> = ({
<VMSSVirtualMachineScaleSets
name={name}
resourceGroups={options.virtualmachinescalesets.resourceGroups}
setDetails={showDetails}
setDetails={setDetails}
/>
</PluginCard>
);
Expand Down
2 changes: 1 addition & 1 deletion plugins/core/src/components/app/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ const HomePage: React.FunctionComponent = () => {
name={pluginDetails.name}
displayName={pluginDetails.displayName}
description={pluginDetails.description}
options={pluginDetails.options}
pluginOptions={pluginDetails.options}
/>
) : activePage === 'account' ? (
<Account />
Expand Down
2 changes: 1 addition & 1 deletion plugins/core/src/components/plugin/PluginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const PluginPage: React.FunctionComponent = () => {
name={pluginDetails.name}
displayName={pluginDetails.displayName}
description={pluginDetails.description}
options={pluginDetails.options}
pluginOptions={pluginDetails.options}
/>
);
};
4 changes: 2 additions & 2 deletions plugins/core/src/components/plugin/PluginPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const PluginPanel: React.FunctionComponent<IPluginPanelProps> = ({
title,
description,
options,
showDetails,
setDetails,
}: IPluginPanelProps) => {
const authContext = useContext<IAuthContext>(AuthContext);

Expand Down Expand Up @@ -56,7 +56,7 @@ export const PluginPanel: React.FunctionComponent<IPluginPanelProps> = ({
description={description}
pluginOptions={pluginDetails.options}
options={options}
showDetails={showDetails}
setDetails={setDetails}
/>
);
};
4 changes: 2 additions & 2 deletions plugins/core/src/context/PluginsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export interface IPluginPageProps {
name: string;
displayName: string;
description: string;
options?: IPluginDataOptions;
pluginOptions?: IPluginDataOptions;
}

// IPluginPanelProps is the interface for the properties of the panel component of each plugin. It contains the already
Expand All @@ -77,7 +77,7 @@ export interface IPluginPanelProps {
pluginOptions?: IPluginDataOptions;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
options?: any;
showDetails?: (details: React.ReactNode) => void;
setDetails?: (details: React.ReactNode) => void;
}

// IPluginPreviewProps is the interface for the properties of the preview component of each plugin. It contains the
Expand Down
14 changes: 11 additions & 3 deletions plugins/core/src/utils/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,24 @@ export const formatTime = (timestamp: number): string => {
};

// getTimeParams returns a times object for the parsed time parameters from a URL.
export const getTimeParams = (params: URLSearchParams): IPluginTimes => {
export const getTimeParams = (params: URLSearchParams, isInitial: boolean): IPluginTimes => {
const time = params.get('time');
const timeEnd = params.get('timeEnd');
const timeStart = params.get('timeStart');

if (time && TTimeOptions.includes(time) && time !== 'custom') {
if (isInitial) {
return {
time: time as TTime,
timeEnd: Math.floor(Date.now() / 1000),
timeStart: Math.floor(Date.now() / 1000) - timeOptions[time].seconds,
};
}

return {
time: time as TTime,
timeEnd: Math.floor(Date.now() / 1000),
timeStart: Math.floor(Date.now() / 1000) - timeOptions[time].seconds,
timeEnd: timeEnd ? parseInt(timeEnd) : Math.floor(Date.now() / 1000),
timeStart: timeStart ? parseInt(timeStart) : Math.floor(Date.now() / 1000) - timeOptions[time].seconds,
};
}

Expand Down
6 changes: 3 additions & 3 deletions plugins/dashboards/src/components/dashboards/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface IDashboardProps {
defaults: IPluginDefaults;
dashboard: IDashboard;
forceDefaultSpan: boolean;
showDetails?: (details: React.ReactNode) => void;
setDetails?: (details: React.ReactNode) => void;
}

// The Dashboard component renders the rows and panels for a single dashboard, by including a plugin via the PluginPanel
Expand All @@ -37,7 +37,7 @@ const Dashboard: React.FunctionComponent<IDashboardProps> = ({
defaults,
dashboard,
forceDefaultSpan,
showDetails,
setDetails,
}: IDashboardProps) => {
const clustersContext = useContext<IClusterContext>(ClustersContext);
const pluginsContext = useContext<IPluginsContext>(PluginsContext);
Expand Down Expand Up @@ -218,7 +218,7 @@ const Dashboard: React.FunctionComponent<IDashboardProps> = ({
description={panel.description}
name={panel.plugin.name}
options={panel.plugin.options}
showDetails={showDetails}
setDetails={setDetails}
/>
</div>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import Dashboard from './Dashboard';
interface IDashboardWrapperProps {
defaults: IPluginDefaults;
dashboard: IDashboard;
showDetails?: (details: React.ReactNode) => void;
setDetails?: (details: React.ReactNode) => void;
}

const DashboardWrapper: React.FunctionComponent<IDashboardWrapperProps> = ({
defaults,
dashboard,
showDetails,
setDetails,
}: IDashboardWrapperProps) => {
const refWrapper = useRef<HTMLDivElement>(null);
const tabsSize = useDimensions(refWrapper);
Expand All @@ -25,7 +25,7 @@ const DashboardWrapper: React.FunctionComponent<IDashboardWrapperProps> = ({
defaults={defaults}
dashboard={dashboard}
forceDefaultSpan={tabsSize.width < 1200}
showDetails={showDetails}
setDetails={setDetails}
/>
</div>
);
Expand Down
Loading