Plugins: Fix double page paddings on plugin admin pages (#48315)

This commit is contained in:
Torkel Ödegaard 2022-04-27 09:56:44 +02:00 committed by GitHub
parent 103087a1a5
commit 8764040fe3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 164 additions and 192 deletions

View File

@ -2,18 +2,14 @@ import React from 'react';
import { LoadingPlaceholder } from '@grafana/ui';
import { Page } from './Page';
export interface Props {
text?: string;
}
export const Loader = ({ text = 'Loading...' }: Props) => {
return (
<Page>
<div className="page-loader-wrapper">
<LoadingPlaceholder text={text} />
</div>
</Page>
<div className="page-loader-wrapper">
<LoadingPlaceholder text={text} />
</div>
);
};

View File

@ -1,19 +0,0 @@
import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';
export const Page: React.FC = ({ children }) => {
const styles = useStyles2(getStyles);
return (
<div className="page-container">
<div className={styles}>{children}</div>
</div>
);
};
const getStyles = (theme: GrafanaTheme2) =>
css`
margin-bottom: ${theme.spacing(3)};
`;

View File

@ -26,75 +26,79 @@ export function PluginDetailsHeader({ plugin, currentUrl, parentUrl }: Props): R
const version = plugin.installedVersion || latestCompatibleVersion?.version;
return (
<div className={styles.headerContainer}>
<PluginLogo
alt={`${plugin.name} logo`}
src={plugin.info.logos.small}
className={css`
object-fit: contain;
width: 100%;
height: 68px;
max-width: 68px;
`}
/>
<div>
<div className="page-container">
<div className={styles.headerContainer}>
<PluginLogo
alt={`${plugin.name} logo`}
src={plugin.info.logos.small}
className={css`
object-fit: contain;
width: 100%;
height: 68px;
max-width: 68px;
`}
/>
<div className={styles.headerWrapper}>
{/* Title & navigation */}
<nav className={styles.breadcrumb} aria-label="Breadcrumb">
<ol>
<li>
<a className={styles.textUnderline} href={parentUrl}>
Plugins
</a>
</li>
<li>
<a href={currentUrl} aria-current="page">
{plugin.name}
</a>
</li>
</ol>
</nav>
<div className={styles.headerWrapper}>
{/* Title & navigation */}
<nav className={styles.breadcrumb} aria-label="Breadcrumb">
<ol>
<li>
<a className={styles.textUnderline} href={parentUrl}>
Plugins
</a>
</li>
<li>
<a href={currentUrl} aria-current="page">
{plugin.name}
</a>
</li>
</ol>
</nav>
<div className={styles.headerInformationRow}>
{/* Org name */}
<span>{plugin.orgName}</span>
<div className={styles.headerInformationRow}>
{/* Org name */}
<span>{plugin.orgName}</span>
{/* Links */}
{plugin.details?.links.map((link: any) => (
<a key={link.name} href={link.url}>
{link.name}
</a>
))}
{/* Links */}
{plugin.details?.links.map((link: any) => (
<a key={link.name} href={link.url}>
{link.name}
</a>
))}
{/* Downloads */}
{plugin.downloads > 0 && (
<span>
<Icon name="cloud-download" />
{` ${new Intl.NumberFormat().format(plugin.downloads)}`}{' '}
</span>
)}
{/* Downloads */}
{plugin.downloads > 0 && (
<span>
<Icon name="cloud-download" />
{` ${new Intl.NumberFormat().format(plugin.downloads)}`}{' '}
</span>
)}
{/* Version */}
{Boolean(version) && <span>{version}</span>}
{/* Version */}
{Boolean(version) && <span>{version}</span>}
{/* Signature information */}
<PluginDetailsHeaderSignature plugin={plugin} />
{/* Signature information */}
<PluginDetailsHeaderSignature plugin={plugin} />
{plugin.isDisabled && <PluginDisabledBadge error={plugin.error!} />}
{plugin.isDisabled && <PluginDisabledBadge error={plugin.error!} />}
</div>
<PluginDetailsHeaderDependencies
plugin={plugin}
latestCompatibleVersion={latestCompatibleVersion}
className={cx(styles.headerInformationRow, styles.headerInformationRowSecondary)}
/>
<p>{plugin.description}</p>
<HorizontalGroup height="auto">
<InstallControls plugin={plugin} latestCompatibleVersion={latestCompatibleVersion} />
<GetStartedWithPlugin plugin={plugin} />
</HorizontalGroup>
</div>
</div>
<PluginDetailsHeaderDependencies
plugin={plugin}
latestCompatibleVersion={latestCompatibleVersion}
className={cx(styles.headerInformationRow, styles.headerInformationRowSecondary)}
/>
<p>{plugin.description}</p>
<HorizontalGroup height="auto">
<InstallControls plugin={plugin} latestCompatibleVersion={latestCompatibleVersion} />
<GetStartedWithPlugin plugin={plugin} />
</HorizontalGroup>
</div>
</div>
);

View File

@ -12,7 +12,6 @@ import { getNavModel } from 'app/core/selectors/navModel';
import { StoreState } from 'app/types/store';
import { HorizontalGroup } from '../components/HorizontalGroup';
import { Page as PluginPage } from '../components/Page';
import { PluginList } from '../components/PluginList';
import { SearchField } from '../components/SearchField';
import { Sorters } from '../helpers';
@ -69,94 +68,92 @@ export default function Browse({ route }: GrafanaRouteComponentProps): ReactElem
return (
<Page navModel={navModel}>
<Page.Contents>
<PluginPage>
<HorizontalGroup wrap>
<SearchField value={query} onSearch={onSearch} />
<HorizontalGroup wrap className={styles.actionBar}>
{/* Filter by type */}
<div>
<RadioButtonGroup
value={filterByType}
onChange={onFilterByTypeChange}
options={[
{ value: 'all', label: 'All' },
{ value: 'datasource', label: 'Data sources' },
{ value: 'panel', label: 'Panels' },
{ value: 'app', label: 'Applications' },
]}
/>
</div>
{/* Filter by installed / all */}
{remotePluginsAvailable ? (
<div>
<RadioButtonGroup value={filterBy} onChange={onFilterByChange} options={filterByOptions} />
</div>
) : (
<Tooltip
content="This filter has been disabled because the Grafana server cannot access grafana.com"
placement="top"
>
<div>
<RadioButtonGroup
disabled={true}
value={filterBy}
onChange={onFilterByChange}
options={filterByOptions}
/>
</div>
</Tooltip>
)}
{/* Sorting */}
<div>
<Select
menuShouldPortal
aria-label="Sort Plugins List"
width={24}
value={sortBy}
onChange={onSortByChange}
options={[
{ value: 'nameAsc', label: 'Sort by name (A-Z)' },
{ value: 'nameDesc', label: 'Sort by name (Z-A)' },
{ value: 'updated', label: 'Sort by updated date' },
{ value: 'published', label: 'Sort by published date' },
{ value: 'downloads', label: 'Sort by downloads' },
]}
/>
</div>
{/* Display mode */}
<div>
<RadioButtonGroup<PluginListDisplayMode>
className={styles.displayAs}
value={displayMode}
onChange={setDisplayMode}
options={[
{
value: PluginListDisplayMode.Grid,
icon: 'table',
description: 'Display plugins in a grid layout',
},
{ value: PluginListDisplayMode.List, icon: 'list-ul', description: 'Display plugins in list' },
]}
/>
</div>
</HorizontalGroup>
</HorizontalGroup>
<div className={styles.listWrap}>
{isLoading ? (
<LoadingPlaceholder
className={css`
margin-bottom: 0;
`}
text="Loading results"
<HorizontalGroup wrap>
<SearchField value={query} onSearch={onSearch} />
<HorizontalGroup wrap className={styles.actionBar}>
{/* Filter by type */}
<div>
<RadioButtonGroup
value={filterByType}
onChange={onFilterByTypeChange}
options={[
{ value: 'all', label: 'All' },
{ value: 'datasource', label: 'Data sources' },
{ value: 'panel', label: 'Panels' },
{ value: 'app', label: 'Applications' },
]}
/>
</div>
{/* Filter by installed / all */}
{remotePluginsAvailable ? (
<div>
<RadioButtonGroup value={filterBy} onChange={onFilterByChange} options={filterByOptions} />
</div>
) : (
<PluginList plugins={plugins} displayMode={displayMode} />
<Tooltip
content="This filter has been disabled because the Grafana server cannot access grafana.com"
placement="top"
>
<div>
<RadioButtonGroup
disabled={true}
value={filterBy}
onChange={onFilterByChange}
options={filterByOptions}
/>
</div>
</Tooltip>
)}
</div>
</PluginPage>
{/* Sorting */}
<div>
<Select
menuShouldPortal
aria-label="Sort Plugins List"
width={24}
value={sortBy}
onChange={onSortByChange}
options={[
{ value: 'nameAsc', label: 'Sort by name (A-Z)' },
{ value: 'nameDesc', label: 'Sort by name (Z-A)' },
{ value: 'updated', label: 'Sort by updated date' },
{ value: 'published', label: 'Sort by published date' },
{ value: 'downloads', label: 'Sort by downloads' },
]}
/>
</div>
{/* Display mode */}
<div>
<RadioButtonGroup<PluginListDisplayMode>
className={styles.displayAs}
value={displayMode}
onChange={setDisplayMode}
options={[
{
value: PluginListDisplayMode.Grid,
icon: 'table',
description: 'Display plugins in a grid layout',
},
{ value: PluginListDisplayMode.List, icon: 'list-ul', description: 'Display plugins in list' },
]}
/>
</div>
</HorizontalGroup>
</HorizontalGroup>
<div className={styles.listWrap}>
{isLoading ? (
<LoadingPlaceholder
className={css`
margin-bottom: 0;
`}
text="Loading results"
/>
) : (
<PluginList plugins={plugins} displayMode={displayMode} />
)}
</div>
</Page.Contents>
</Page>
);

View File

@ -4,8 +4,6 @@ import React from 'react';
import { NavModel, NavModelItem } from '@grafana/data';
import { Page } from 'app/core/components/Page/Page';
import { Page as PluginPage } from '../components/Page';
const node: NavModelItem = {
id: 'not-found',
text: 'The plugin catalog is not enabled',
@ -19,18 +17,16 @@ export default function NotEnabled(): JSX.Element | null {
return (
<Page navModel={navModel}>
<Page.Contents>
<PluginPage>
To enable installing plugins via catalog, please refer to the{' '}
<a
className={css`
text-decoration: underline;
`}
href="https://grafana.com/docs/grafana/latest/plugins/catalog"
>
Plugin Catalog
</a>{' '}
instructions
</PluginPage>
To enable installing plugins via catalog, please refer to the{' '}
<a
className={css`
text-decoration: underline;
`}
href="https://grafana.com/docs/grafana/latest/plugins/catalog"
>
Plugin Catalog
</a>{' '}
instructions
</Page.Contents>
</Page>
);

View File

@ -11,7 +11,6 @@ import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { AppNotificationSeverity } from 'app/types';
import { Loader } from '../components/Loader';
import { Page as PluginPage } from '../components/Page';
import { PluginDetailsBody } from '../components/PluginDetailsBody';
import { PluginDetailsDisabledError } from '../components/PluginDetailsDisabledError';
import { PluginDetailsHeader } from '../components/PluginDetailsHeader';
@ -75,9 +74,8 @@ export default function PluginDetails({ match, queryParams }: Props): JSX.Elemen
return (
<Page>
<PluginPage>
<PluginDetailsHeader currentUrl={`${url}?page=${pageId}`} parentUrl={parentUrl} plugin={plugin} />
<PluginDetailsHeader currentUrl={`${url}?page=${pageId}`} parentUrl={parentUrl} plugin={plugin} />
<Page.Contents>
{/* Tab navigation */}
<TabsBar>
{tabs.map((tab: PluginDetailsTab) => {
@ -99,7 +97,7 @@ export default function PluginDetails({ match, queryParams }: Props): JSX.Elemen
<PluginDetailsDisabledError plugin={plugin} className={styles.alert} />
<PluginDetailsBody queryParams={queryParams} plugin={plugin} pageId={pageId} />
</TabContent>
</PluginPage>
</Page.Contents>
</Page>
);
}