mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
News: Add loading skeleton (#79009)
* convert to emotion object syntax * add news skeleton
This commit is contained in:
parent
99d893fd30
commit
bae9dbe418
@ -6339,18 +6339,6 @@ exports[`better eslint`] = {
|
|||||||
"public/app/plugins/panel/logs/LogsPanel.tsx:5381": [
|
"public/app/plugins/panel/logs/LogsPanel.tsx:5381": [
|
||||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||||
],
|
],
|
||||||
"public/app/plugins/panel/news/component/News.tsx:5381": [
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "0"],
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "1"],
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "2"],
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "3"],
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "4"],
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "5"],
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "6"],
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "7"],
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "8"],
|
|
||||||
[0, 0, 0, "Styles should be written using objects.", "9"]
|
|
||||||
],
|
|
||||||
"public/app/plugins/panel/nodeGraph/Edge.tsx:5381": [
|
"public/app/plugins/panel/nodeGraph/Edge.tsx:5381": [
|
||||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||||
],
|
],
|
||||||
|
@ -3,7 +3,7 @@ import React, { useEffect } from 'react';
|
|||||||
import { useMeasure } from 'react-use';
|
import { useMeasure } from 'react-use';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
import { News } from 'app/plugins/panel/news/component/News';
|
import { News } from 'app/plugins/panel/news/component/News';
|
||||||
import { useNewsFeed } from 'app/plugins/panel/news/useNewsFeed';
|
import { useNewsFeed } from 'app/plugins/panel/news/useNewsFeed';
|
||||||
|
|
||||||
@ -19,25 +19,28 @@ export function NewsWrapper({ feedUrl }: NewsWrapperProps) {
|
|||||||
getNews();
|
getNews();
|
||||||
}, [getNews]);
|
}, [getNews]);
|
||||||
|
|
||||||
if (state.loading || state.error) {
|
if (state.error) {
|
||||||
return (
|
return <div className={styles.innerWrapper}>{state.error && state.error.message}</div>;
|
||||||
<div className={styles.innerWrapper}>
|
|
||||||
{state.loading && <LoadingPlaceholder text="Loading..." />}
|
|
||||||
{state.error && state.error.message}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state.value) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={widthRef}>
|
<div ref={widthRef}>
|
||||||
{widthMeasure.width > 0 &&
|
{state.loading ? (
|
||||||
state.value.map((_, index) => (
|
<>
|
||||||
<News key={index} index={index} showImage width={widthMeasure.width} data={state.value} />
|
<News.Skeleton showImage width={widthMeasure.width} />
|
||||||
))}
|
<News.Skeleton showImage width={widthMeasure.width} />
|
||||||
|
<News.Skeleton showImage width={widthMeasure.width} />
|
||||||
|
<News.Skeleton showImage width={widthMeasure.width} />
|
||||||
|
<News.Skeleton showImage width={widthMeasure.width} />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{widthMeasure.width > 0 &&
|
||||||
|
state.value?.map((_, index) => (
|
||||||
|
<News key={index} index={index} showImage width={widthMeasure.width} data={state.value} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<div className={styles.grot}>
|
<div className={styles.grot}>
|
||||||
<a href="https://grafana.com/blog/" target="_blank" rel="noreferrer" title="Go to Grafana labs blog">
|
<a href="https://grafana.com/blog/" target="_blank" rel="noreferrer" title="Go to Grafana labs blog">
|
||||||
<img src="public/img/grot-news.svg" alt="Grot reading news" />
|
<img src="public/img/grot-news.svg" alt="Grot reading news" />
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Skeleton from 'react-loading-skeleton';
|
||||||
|
|
||||||
import { DataFrameView, GrafanaTheme2, textUtil, dateTimeFormat } from '@grafana/data';
|
import { DataFrameView, GrafanaTheme2, textUtil, dateTimeFormat } from '@grafana/data';
|
||||||
import { useStyles2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
@ -45,68 +46,93 @@ export function News({ width, showImage, data, index }: NewsItemProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => ({
|
const NewsSkeleton = ({ width, showImage }: Pick<NewsItemProps, 'width' | 'showImage'>) => {
|
||||||
container: css`
|
const styles = useStyles2(getStyles);
|
||||||
height: 100%;
|
const useWideLayout = width > 600;
|
||||||
`,
|
|
||||||
item: css`
|
|
||||||
display: flex;
|
|
||||||
padding: ${theme.spacing(1)};
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
margin-right: ${theme.spacing(1)};
|
|
||||||
border-bottom: 2px solid ${theme.colors.border.weak};
|
|
||||||
background: ${theme.colors.background.primary};
|
|
||||||
flex-direction: column;
|
|
||||||
flex-shrink: 0;
|
|
||||||
`,
|
|
||||||
itemWide: css`
|
|
||||||
flex-direction: row;
|
|
||||||
`,
|
|
||||||
body: css`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
`,
|
|
||||||
socialImage: css`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: ${theme.spacing(1)};
|
|
||||||
> img {
|
|
||||||
width: 100%;
|
|
||||||
border-radius: ${theme.shape.radius.default} ${theme.shape.radius.default} 0 0;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
socialImageWide: css`
|
|
||||||
margin-right: ${theme.spacing(2)};
|
|
||||||
margin-bottom: 0;
|
|
||||||
> img {
|
|
||||||
width: 250px;
|
|
||||||
border-radius: ${theme.shape.radius.default};
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
link: css`
|
|
||||||
color: ${theme.colors.text.link};
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
&:hover {
|
return (
|
||||||
color: ${theme.colors.text.link};
|
<div className={cx(styles.item, useWideLayout && styles.itemWide)}>
|
||||||
text-decoration: underline;
|
{showImage && (
|
||||||
}
|
<Skeleton
|
||||||
`,
|
containerClassName={cx(styles.socialImage, useWideLayout && styles.socialImageWide)}
|
||||||
title: css`
|
width={useWideLayout ? '250px' : '100%'}
|
||||||
font-size: 16px;
|
height={useWideLayout ? '150px' : width * 0.5}
|
||||||
margin-bottom: ${theme.spacing(0.5)};
|
/>
|
||||||
`,
|
)}
|
||||||
content: css`
|
<div className={styles.body}>
|
||||||
p {
|
<Skeleton containerClassName={styles.date} width={60} />
|
||||||
margin-bottom: 4px;
|
<Skeleton containerClassName={styles.title} width={250} />
|
||||||
color: ${theme.colors.text};
|
<Skeleton containerClassName={styles.content} width="100%" count={6} />
|
||||||
}
|
</div>
|
||||||
`,
|
</div>
|
||||||
date: css`
|
);
|
||||||
margin-bottom: ${theme.spacing(0.5)};
|
};
|
||||||
font-weight: 500;
|
|
||||||
border-radius: 0 0 0 ${theme.shape.radius.default};
|
News.Skeleton = NewsSkeleton;
|
||||||
color: ${theme.colors.text.secondary};
|
|
||||||
`,
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
|
container: css({
|
||||||
|
height: '100%',
|
||||||
|
}),
|
||||||
|
item: css({
|
||||||
|
display: 'flex',
|
||||||
|
padding: theme.spacing(1),
|
||||||
|
position: 'relative',
|
||||||
|
marginBottom: theme.spacing(0.5),
|
||||||
|
marginRight: theme.spacing(1),
|
||||||
|
borderBottom: `2px solid ${theme.colors.border.weak}`,
|
||||||
|
background: theme.colors.background.primary,
|
||||||
|
flexDirection: 'column',
|
||||||
|
flexShrink: 0,
|
||||||
|
}),
|
||||||
|
itemWide: css({
|
||||||
|
flexDirection: 'row',
|
||||||
|
}),
|
||||||
|
body: css({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
flex: 1,
|
||||||
|
}),
|
||||||
|
socialImage: css({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: theme.spacing(1),
|
||||||
|
'> img': {
|
||||||
|
width: '100%',
|
||||||
|
borderRadius: `${theme.shape.radius.default} ${theme.shape.radius.default} 0 0`,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
socialImageWide: css({
|
||||||
|
marginRight: theme.spacing(2),
|
||||||
|
marginBottom: 0,
|
||||||
|
'> img': {
|
||||||
|
width: '250px',
|
||||||
|
borderRadius: theme.shape.radius.default,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
link: css({
|
||||||
|
color: theme.colors.text.link,
|
||||||
|
display: 'inline-block',
|
||||||
|
|
||||||
|
'&:hover': {
|
||||||
|
color: theme.colors.text.link,
|
||||||
|
textDecoration: 'underline',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
title: css({
|
||||||
|
fontSize: '16px',
|
||||||
|
marginBottom: theme.spacing(0.5),
|
||||||
|
}),
|
||||||
|
content: css({
|
||||||
|
p: {
|
||||||
|
marginBottom: theme.spacing(0.5),
|
||||||
|
color: theme.colors.text.primary,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
date: css({
|
||||||
|
marginBottom: theme.spacing(0.5),
|
||||||
|
fontWeight: 500,
|
||||||
|
borderRadius: `0 0 0 ${theme.shape.radius.default}`,
|
||||||
|
color: theme.colors.text.secondary,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user