Skip to content

Commit

Permalink
Feat/rework config page (#990)
Browse files Browse the repository at this point in the history
* chore: migrate to `react-router-dom@v6` (with `react-router-dom-v5-compat`

- update routes
- remove unused code
- add `NotFound` page (wip)

* chore: update summary table links

* chore: create-plugin update

- fix type issues
- remove redundant variable
- fix tests (most of them)

* chore: fix more tests

- fix bug in `useSearchQueryParametersState`

* chore: redirect to `home`

* chore: update to node `v20`
- downgrade packages to match grafana `grafanaDependency` version

* feat: secrets management

- create feature toggle for POC
- create tab content container
- adapt current config page to the tabbed view

* fix: add missing line break

* fix: self-review change requests

- use `generateRoutePath`
- remove done TODOs
- update tests for `ProbeCard`
- update tests for `NewProbe`
- update tests for `EditProbe`
- remove debug content from `TestRouteInfo`

* fix: self-review change requests

- update not found usage for `EditProbe`

* feat: add dedicated `pluginConfig` page

* chore: clean up

* chore: migrate to `react-router-dom@v6` (with `react-router-dom-v5-compat`

- update routes
- remove unused code
- add `NotFound` page (wip)

* chore: update summary table links

* chore: create-plugin update

- fix type issues
- remove redundant variable
- fix tests (most of them)

* chore: fix more tests

- fix bug in `useSearchQueryParametersState`

* chore: redirect to `home`

* chore: update to node `v20`
- downgrade packages to match grafana `grafanaDependency` version

* fix: add missing line break

* fix: self-review change requests

- use `generateRoutePath`
- remove done TODOs
- update tests for `ProbeCard`
- update tests for `NewProbe`
- update tests for `EditProbe`
- remove debug content from `TestRouteInfo`

* fix: self-review change requests

- update not found usage for `EditProbe`

* fix: pr change requests

- lock grafana dependencies on 11.3.0
- add 404 page instead of redirect to Home

* chore: update `yarn.lock` after rebase

* fix: remove comment

- update `yarn.lock`

* fix: self-review

- remove `@ts-ignore`
- remove extra padding
- remove random "Hello" element
- shorten imports
- remove unused `ROUTES`

* fix: chris CRs

- heading order

* fix: chris CRs
- change h1 to h2 on plugin config page
- remove `console.log`
- move `AppInitializer`

* fix: re-style headings on config page

* fix: replace CSS syntax for object syntax

* fix: vikas CRs
  • Loading branch information
w1kman authored Nov 25, 2024
1 parent 61073a3 commit 56b05c3
Show file tree
Hide file tree
Showing 50 changed files with 1,494 additions and 552 deletions.
72 changes: 0 additions & 72 deletions src/components/AccessToken.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { PropsWithChildren } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Alert, Button, Spinner, useStyles2 } from '@grafana/ui';
import { css } from '@emotion/css';
import { DataTestIds } from 'test/dataTestIds';

import { ROUTES } from 'types';
import { hasGlobalPermission } from 'utils';
Expand All @@ -14,6 +15,7 @@ interface Props {
buttonText: string;
}

// TODO: Does this really belong under /page?
export const AppInitializer = ({ redirectTo, buttonText }: PropsWithChildren<Props>) => {
const { jsonData } = useMeta();
const styles = useStyles2(getStyles);
Expand Down Expand Up @@ -42,7 +44,7 @@ export const AppInitializer = ({ redirectTo, buttonText }: PropsWithChildren<Pro
}

return (
<div>
<div data-testid={DataTestIds.APP_INITIALIZER}>
<Button onClick={handleClick} disabled={loading} size="lg">
{loading ? <Spinner /> : buttonText}
</Button>
Expand Down
25 changes: 0 additions & 25 deletions src/components/BackendAddress/BackendAddress.tsx

This file was deleted.

1 change: 0 additions & 1 deletion src/components/BackendAddress/index.ts

This file was deleted.

19 changes: 8 additions & 11 deletions src/components/Clipboard/Clipboard.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import React from 'react';
import { AppEvents } from '@grafana/data';
import { useStyles } from '@grafana/ui';
import { useStyles2 } from '@grafana/ui';
import appEvents from 'grafana/app/core/app_events';
import { css, cx } from '@emotion/css';

import { Preformatted } from '../Preformatted';
import { CopyToClipboard } from './CopyToClipboard';

const getStyles = () => ({
code: css`
width: 100%;
word-break: break-all;
overflow-y: scroll;
max-height: 100%;
`,
container: css`
display: flex;
flex-direction: column;
Expand All @@ -26,16 +21,18 @@ interface Props {
content: string;
className?: string;
truncate?: boolean;
highlight?: string | string[];
isCode?: boolean;
}

export function Clipboard({ content, className, truncate }: Props) {
const styles = useStyles(getStyles);
export function Clipboard({ content, className, truncate, highlight, isCode }: Props) {
const styles = useStyles2(getStyles);

return (
<div className={cx(styles.container, className)}>
<pre className={styles.code} data-testid="clipboard-content">
<Preformatted isCode={isCode} highlight={highlight} data-testid="clipboard-content">
{truncate ? content.slice(0, 150) + '...' : content}
</pre>
</Preformatted>

<CopyToClipboard
className={styles.button}
Expand Down
21 changes: 0 additions & 21 deletions src/components/ConfigPageWrapper.tsx

This file was deleted.

39 changes: 28 additions & 11 deletions src/components/LinkedDatasourceView.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,62 @@
import React from 'react';
import { Alert, Card, Tag } from '@grafana/ui';

import { useCanWriteLogs, useCanWriteMetrics } from 'hooks/useDSPermission';
import { useCanWriteLogs, useCanWriteMetrics, useCanWriteSM } from 'hooks/useDSPermission';
import { useLogsDS } from 'hooks/useLogsDS';
import { useMetricsDS } from 'hooks/useMetricsDS';
import { useSMDS } from 'hooks/useSMDS';

interface LinkedDatasourceViewProps {
type: 'loki' | 'prometheus';
type: 'loki' | 'prometheus' | 'synthetic-monitoring-datasource';
}

export const LinkedDatasourceView = ({ type }: LinkedDatasourceViewProps) => {
const metricsDS = useMetricsDS();
const logsDS = useLogsDS();
const smDS = useSMDS();

const canEditSM = useCanWriteSM();
const canEditLogs = useCanWriteLogs();
const canEditMetrics = useCanWriteMetrics();

const canEditMap = {
prometheus: canEditMetrics,
loki: canEditLogs,
'synthetic-monitoring-datasource': canEditSM,
};

const dsMap = {
prometheus: metricsDS,
loki: logsDS,
'synthetic-monitoring-datasource': smDS,
};

const ds = dsMap[type];

if (!ds) {
return null;
return (
<Alert title="Data source missing">
&quot;{type}&quot; data source is missing. Please configure it in the data sources settings.
</Alert>
);
}

const showHref = canEditMap[type];
const Tag = showHref ? 'a' : 'div';

return (
<Tag className="add-data-source-item" href={showHref ? `datasources/edit/${ds.uid}/` : undefined}>
<img className="add-data-source-item-logo" src={ds.meta.info.logos.small} alt="" />
<div className="add-data-source-item-text-wrapper">
<span className="add-data-source-item-text">{ds.name}</span>
<span className="add-data-source-item-desc">{ds.type}</span>
</div>
</Tag>
<Card href={showHref ? `datasources/edit/${ds.uid}/` : undefined}>
<Card.Heading>{ds.name}</Card.Heading>
<Card.Figure>
<img width={40} height={40} src={ds.meta.info.logos.small} alt="" />
</Card.Figure>

{type !== 'synthetic-monitoring-datasource' && (
<Card.Tags>
<Tag name="Linked" />
</Card.Tags>
)}

<Card.Meta>{ds.type}</Card.Meta>
</Card>
);
};
75 changes: 75 additions & 0 deletions src/components/Preformatted.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import { render, screen, within } from '@testing-library/react';

import { Preformatted } from './Preformatted';

describe('Preformatted', () => {
it('should render content within a pre tag', async () => {
const sampleContent = '__sample_content__';
render(<Preformatted>{sampleContent}</Preformatted>);
const pre = screen.queryByText(sampleContent);

expect(pre).toBeInTheDocument();
});

it('should render content within a pre tag, within a code tag', async () => {
const sampleContent = '__sample_content__';
render(<Preformatted isCode>{sampleContent}</Preformatted>);
const pre = screen.queryByText(sampleContent, { selector: 'code' });

expect(pre).toBeInTheDocument();
});

it.each([
{
highlight: '__sample__',
content: `This is a __sample__ content.`, // Note: 'This' is used to find the pre tag
expectedLength: 1,
},
{
highlight: '__target__',
content: `This should highlight __target__ and __target__`, // Note: 'This' is used to find the pre tag
expectedLength: 2,
},
])(
'should take string as highlight prop ($expectedLength counts)',
async ({ highlight, content, expectedLength }) => {
render(<Preformatted highlight={highlight}>{content}</Preformatted>);

const pre = screen.getByText(/^This/, { selector: 'pre' });
expect(pre).toBeInTheDocument();
const highlighted = pre && within(pre).queryAllByText(highlight, { selector: 'strong' });
expect(highlighted).toHaveLength(expectedLength);
}
);

it.each([
{
highlight: ['__sample__'],
content: `This should replace __sample__`, // Note: 'This' is used to find the pre tag
expectedLength: 1,
},
{
highlight: ['__sample__', '__target__'],
content: `This should replace __sample__ and __target__`, // Note: 'This' is used to find the pre tag
expectedLength: 2,
},
{
highlight: ['__sample__', '__target__', '__another__'],
content: `This should replace __sample__, __another__ and __target__`, // Note: 'This' is used to find the pre tag
expectedLength: 3,
},
])('should take array as highlight prop ($expectedLength counts)', async ({ highlight, content, expectedLength }) => {
render(<Preformatted highlight={highlight}>{content}</Preformatted>);

const pre = screen.getByText(/^This/, { selector: 'pre' });
expect(pre).toBeInTheDocument();

const count = highlight.reduce((acc, word) => {
const match = pre && within(pre).queryAllByText(word, { selector: 'strong' });
return acc + match.length;
}, 0);

expect(count).toBe(expectedLength);
});
});
Loading

0 comments on commit 56b05c3

Please sign in to comment.