Explore: Rename RichHistoryCard for clarity and consistency (#78358)

Rename for clarity and consistency
pull/78407/head
Haris Rozajac 2 years ago committed by GitHub
parent 3e5dfa2d02
commit 499915ff9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 38
      public/app/features/explore/RichHistory/RichHistoryCard.test.tsx
  2. 83
      public/app/features/explore/RichHistory/RichHistoryCard.tsx
  3. 2
      public/app/features/explore/RichHistory/RichHistoryQueriesTab.tsx
  4. 2
      public/app/features/explore/RichHistory/RichHistoryStarredTab.tsx

@ -106,7 +106,7 @@ interface MockQuery extends DataQuery {
const setup = (propOverrides?: Partial<Props<MockQuery>>) => { const setup = (propOverrides?: Partial<Props<MockQuery>>) => {
const props: Props<MockQuery> = { const props: Props<MockQuery> = {
query: { queryHistoryItem: {
id: '1', id: '1',
createdAt: 1, createdAt: 1,
datasourceUid: 'loki', datasourceUid: 'loki',
@ -170,7 +170,7 @@ describe('RichHistoryCard', () => {
it('should render "Data source does not exist anymore" if removed data source', async () => { it('should render "Data source does not exist anymore" if removed data source', async () => {
setup({ setup({
query: { queryHistoryItem: {
id: '2', id: '2',
createdAt: 1, createdAt: 1,
datasourceUid: 'non-existent DS', datasourceUid: 'non-existent DS',
@ -191,7 +191,7 @@ describe('RichHistoryCard', () => {
describe('copy queries to clipboard', () => { describe('copy queries to clipboard', () => {
it('should copy query model to clipboard when copying a query from a non existent datasource', async () => { it('should copy query model to clipboard when copying a query from a non existent datasource', async () => {
setup({ setup({
query: { queryHistoryItem: {
id: '2', id: '2',
createdAt: 1, createdAt: 1,
datasourceUid: 'non-existent DS', datasourceUid: 'non-existent DS',
@ -210,7 +210,7 @@ describe('RichHistoryCard', () => {
it('should copy query model to clipboard when copying a query from a datasource that does not implement getQueryDisplayText', async () => { it('should copy query model to clipboard when copying a query from a datasource that does not implement getQueryDisplayText', async () => {
setup({ setup({
query: { queryHistoryItem: {
id: '2', id: '2',
createdAt: 1, createdAt: 1,
datasourceUid: 'loki', datasourceUid: 'loki',
@ -229,7 +229,7 @@ describe('RichHistoryCard', () => {
it('should copy query text to clipboard when copying a query from a datasource that implements getQueryDisplayText', async () => { it('should copy query text to clipboard when copying a query from a datasource that implements getQueryDisplayText', async () => {
setup({ setup({
query: { queryHistoryItem: {
id: '2', id: '2',
createdAt: 1, createdAt: 1,
datasourceUid: 'prometheus', datasourceUid: 'prometheus',
@ -248,7 +248,7 @@ describe('RichHistoryCard', () => {
it('should use each datasource getQueryDisplayText when copying queries', async () => { it('should use each datasource getQueryDisplayText when copying queries', async () => {
setup({ setup({
query: { queryHistoryItem: {
id: '2', id: '2',
createdAt: 1, createdAt: 1,
datasourceUid: 'mixed', datasourceUid: 'mixed',
@ -280,7 +280,7 @@ describe('RichHistoryCard', () => {
setup({ setup({
setQueries, setQueries,
changeDatasource, changeDatasource,
query: { queryHistoryItem: {
id: '2', id: '2',
createdAt: 1, createdAt: 1,
datasourceUid: 'mixed', datasourceUid: 'mixed',
@ -305,7 +305,7 @@ describe('RichHistoryCard', () => {
setup({ setup({
setQueries, setQueries,
changeDatasource, changeDatasource,
query: { queryHistoryItem: {
id: '2', id: '2',
createdAt: 1, createdAt: 1,
datasourceUid: 'nonexistent-ds', datasourceUid: 'nonexistent-ds',
@ -330,7 +330,7 @@ describe('RichHistoryCard', () => {
setup({ setup({
setQueries, setQueries,
changeDatasource, changeDatasource,
query: { queryHistoryItem: {
id: '2', id: '2',
createdAt: 1, createdAt: 1,
datasourceUid: 'loki', datasourceUid: 'loki',
@ -358,7 +358,7 @@ describe('RichHistoryCard', () => {
setup({ setup({
setQueries, setQueries,
changeDatasource, changeDatasource,
query: { queryHistoryItem: {
id: '2', id: '2',
createdAt: 1, createdAt: 1,
datasourceUid: 'mixed', datasourceUid: 'mixed',
@ -381,13 +381,13 @@ describe('RichHistoryCard', () => {
describe('commenting', () => { describe('commenting', () => {
it('should render comment, if comment present', async () => { it('should render comment, if comment present', async () => {
setup({ query: starredQueryWithComment }); setup({ queryHistoryItem: starredQueryWithComment });
const queryComment = await screen.findByLabelText('Query comment'); const queryComment = await screen.findByLabelText('Query comment');
expect(queryComment).toBeInTheDocument(); expect(queryComment).toBeInTheDocument();
expect(queryComment).toHaveTextContent('test comment'); expect(queryComment).toHaveTextContent('test comment');
}); });
it('should have title "Edit comment" at comment icon, if comment present', async () => { it('should have title "Edit comment" at comment icon, if comment present', async () => {
setup({ query: starredQueryWithComment }); setup({ queryHistoryItem: starredQueryWithComment });
const editComment = await screen.findByLabelText('Edit comment'); const editComment = await screen.findByLabelText('Edit comment');
const addComment = screen.queryByTitle('Add comment'); const addComment = screen.queryByTitle('Add comment');
expect(editComment).toBeInTheDocument(); expect(editComment).toBeInTheDocument();
@ -401,14 +401,14 @@ describe('RichHistoryCard', () => {
expect(editComment).not.toBeInTheDocument(); expect(editComment).not.toBeInTheDocument();
}); });
it('should open update comment form when edit comment button clicked', async () => { it('should open update comment form when edit comment button clicked', async () => {
setup({ query: starredQueryWithComment }); setup({ queryHistoryItem: starredQueryWithComment });
const editComment = await screen.findByLabelText('Edit comment'); const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment); await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form'); const updateCommentForm = await screen.findByLabelText('Update comment form');
expect(updateCommentForm).toBeInTheDocument(); expect(updateCommentForm).toBeInTheDocument();
}); });
it('should close update comment form when escape key pressed', async () => { it('should close update comment form when escape key pressed', async () => {
setup({ query: starredQueryWithComment }); setup({ queryHistoryItem: starredQueryWithComment });
const editComment = await screen.findByLabelText('Edit comment'); const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment); await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form'); const updateCommentForm = await screen.findByLabelText('Update comment form');
@ -420,7 +420,7 @@ describe('RichHistoryCard', () => {
expect(findCommentForm).not.toBeInTheDocument(); expect(findCommentForm).not.toBeInTheDocument();
}); });
it('should close update comment form when enter and shift keys pressed', async () => { it('should close update comment form when enter and shift keys pressed', async () => {
setup({ query: starredQueryWithComment }); setup({ queryHistoryItem: starredQueryWithComment });
const editComment = await screen.findByLabelText('Edit comment'); const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment); await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form'); const updateCommentForm = await screen.findByLabelText('Update comment form');
@ -433,7 +433,7 @@ describe('RichHistoryCard', () => {
expect(findCommentForm).not.toBeInTheDocument(); expect(findCommentForm).not.toBeInTheDocument();
}); });
it('should close update comment form when enter and ctrl keys pressed', async () => { it('should close update comment form when enter and ctrl keys pressed', async () => {
setup({ query: starredQueryWithComment }); setup({ queryHistoryItem: starredQueryWithComment });
const editComment = await screen.findByLabelText('Edit comment'); const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment); await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form'); const updateCommentForm = await screen.findByLabelText('Update comment form');
@ -446,7 +446,7 @@ describe('RichHistoryCard', () => {
expect(findCommentForm).not.toBeInTheDocument(); expect(findCommentForm).not.toBeInTheDocument();
}); });
it('should not close update comment form when enter key pressed', async () => { it('should not close update comment form when enter key pressed', async () => {
setup({ query: starredQueryWithComment }); setup({ queryHistoryItem: starredQueryWithComment });
const editComment = await screen.findByLabelText('Edit comment'); const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment); await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form'); const updateCommentForm = await screen.findByLabelText('Update comment form');
@ -469,7 +469,7 @@ describe('RichHistoryCard', () => {
expect(starRichHistoryMock).toBeCalledWith(starredQueryWithComment.id, true); expect(starRichHistoryMock).toBeCalledWith(starredQueryWithComment.id, true);
}); });
it('should have title "Unstar query", if not starred', async () => { it('should have title "Unstar query", if not starred', async () => {
setup({ query: starredQueryWithComment }); setup({ queryHistoryItem: starredQueryWithComment });
const unstarButton = await screen.findByLabelText('Unstar query'); const unstarButton = await screen.findByLabelText('Unstar query');
expect(unstarButton).toBeInTheDocument(); expect(unstarButton).toBeInTheDocument();
await userEvent.click(unstarButton); await userEvent.click(unstarButton);
@ -486,7 +486,7 @@ describe('RichHistoryCard', () => {
expect(deleteRichHistoryMock).toBeCalledWith(starredQueryWithComment.id); expect(deleteRichHistoryMock).toBeCalledWith(starredQueryWithComment.id);
}); });
it('should display modal before deleting if starred', async () => { it('should display modal before deleting if starred', async () => {
setup({ query: starredQueryWithComment }); setup({ queryHistoryItem: starredQueryWithComment });
const deleteButton = await screen.findByLabelText('Delete query'); const deleteButton = await screen.findByLabelText('Delete query');
await userEvent.click(deleteButton); await userEvent.click(deleteButton);
expect(deleteRichHistoryMock).not.toBeCalled(); expect(deleteRichHistoryMock).not.toBeCalled();

@ -41,7 +41,7 @@ const mapDispatchToProps = {
const connector = connect(mapStateToProps, mapDispatchToProps); const connector = connect(mapStateToProps, mapDispatchToProps);
interface OwnProps<T extends DataQuery = DataQuery> { interface OwnProps<T extends DataQuery = DataQuery> {
query: RichHistoryQuery<T>; queryHistoryItem: RichHistoryQuery<T>;
} }
export type Props<T extends DataQuery = DataQuery> = ConnectedProps<typeof connector> & OwnProps<T>; export type Props<T extends DataQuery = DataQuery> = ConnectedProps<typeof connector> & OwnProps<T>;
@ -142,7 +142,7 @@ const getStyles = (theme: GrafanaTheme2) => {
export function RichHistoryCard(props: Props) { export function RichHistoryCard(props: Props) {
const { const {
query, queryHistoryItem,
commentHistoryItem, commentHistoryItem,
starHistoryItem, starHistoryItem,
deleteHistoryItem, deleteHistoryItem,
@ -151,25 +151,26 @@ export function RichHistoryCard(props: Props) {
datasourceInstance, datasourceInstance,
setQueries, setQueries,
} = props; } = props;
const [activeUpdateComment, setActiveUpdateComment] = useState(false); const [activeUpdateComment, setActiveUpdateComment] = useState(false);
const [comment, setComment] = useState<string | undefined>(query.comment); const [comment, setComment] = useState<string | undefined>(queryHistoryItem.comment);
const { value, loading } = useAsync(async () => { const { value: historyCardData, loading } = useAsync(async () => {
let dsInstance: DataSourceApi | undefined; let datasourceInstance: DataSourceApi | undefined;
try { try {
dsInstance = await getDataSourceSrv().get(query.datasourceUid); datasourceInstance = await getDataSourceSrv().get(queryHistoryItem.datasourceUid);
} catch (e) {} } catch (e) {}
return { return {
dsInstance, datasourceInstance,
queries: await Promise.all( queries: await Promise.all(
query.queries.map(async (query) => { queryHistoryItem.queries.map(async (query) => {
let datasource; let datasource;
if (dsInstance?.meta.mixed) { if (datasourceInstance?.meta.mixed) {
try { try {
datasource = await getDataSourceSrv().get(query.datasource); datasource = await getDataSourceSrv().get(query.datasource);
} catch (e) {} } catch (e) {}
} else { } else {
datasource = dsInstance; datasource = datasourceInstance;
} }
return { return {
@ -179,15 +180,15 @@ export function RichHistoryCard(props: Props) {
}) })
), ),
}; };
}, [query.datasourceUid, query.queries]); }, [queryHistoryItem.datasourceUid, queryHistoryItem.queries]);
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const onRunQuery = async () => { const onRunQuery = async () => {
const queriesToRun = query.queries; const queriesToRun = queryHistoryItem.queries;
const differentDataSource = query.datasourceUid !== datasourceInstance?.uid; const differentDataSource = queryHistoryItem.datasourceUid !== datasourceInstance?.uid;
if (differentDataSource) { if (differentDataSource) {
await changeDatasource(exploreId, query.datasourceUid); await changeDatasource(exploreId, queryHistoryItem.datasourceUid);
} }
setQueries(exploreId, queriesToRun); setQueries(exploreId, queriesToRun);
@ -198,19 +199,19 @@ export function RichHistoryCard(props: Props) {
}; };
const onCopyQuery = async () => { const onCopyQuery = async () => {
const datasources = [...query.queries.map((q) => q.datasource?.type || 'unknown')]; const datasources = [...queryHistoryItem.queries.map((query) => query.datasource?.type || 'unknown')];
reportInteraction('grafana_explore_query_history_copy_query', { reportInteraction('grafana_explore_query_history_copy_query', {
datasources, datasources,
mixed: Boolean(value?.dsInstance?.meta.mixed), mixed: Boolean(historyCardData?.datasourceInstance?.meta.mixed),
}); });
if (loading || !value) { if (loading || !historyCardData) {
return; return;
} }
const queriesText = value.queries const queriesText = historyCardData.queries
.map((q) => { .map((query) => {
return createQueryText(q.query, q.datasource); return createQueryText(query.query, query.datasource);
}) })
.join('\n'); .join('\n');
@ -223,7 +224,7 @@ export function RichHistoryCard(props: Props) {
}; };
const onCreateShortLink = async () => { const onCreateShortLink = async () => {
const link = createUrlFromRichHistory(query); const link = createUrlFromRichHistory(queryHistoryItem);
await createAndCopyShortLink(link); await createAndCopyShortLink(link);
}; };
@ -239,7 +240,7 @@ export function RichHistoryCard(props: Props) {
}; };
// For starred queries, we want confirmation. For non-starred, we don't. // For starred queries, we want confirmation. For non-starred, we don't.
if (query.starred) { if (queryHistoryItem.starred) {
getAppEvents().publish( getAppEvents().publish(
new ShowConfirmModalEvent({ new ShowConfirmModalEvent({
title: t('explore.rich-history-card.delete-query-confirmation-title', 'Delete'), title: t('explore.rich-history-card.delete-query-confirmation-title', 'Delete'),
@ -249,26 +250,26 @@ export function RichHistoryCard(props: Props) {
), ),
yesText: t('explore.rich-history-card.confirm-delete', 'Delete'), yesText: t('explore.rich-history-card.confirm-delete', 'Delete'),
icon: 'trash-alt', icon: 'trash-alt',
onConfirm: () => performDelete(query.id), onConfirm: () => performDelete(queryHistoryItem.id),
}) })
); );
} else { } else {
performDelete(query.id); performDelete(queryHistoryItem.id);
} }
}; };
const onStarrQuery = () => { const onStarrQuery = () => {
starHistoryItem(query.id, !query.starred); starHistoryItem(queryHistoryItem.id, !queryHistoryItem.starred);
reportInteraction('grafana_explore_query_history_starred', { reportInteraction('grafana_explore_query_history_starred', {
queryHistoryEnabled: config.queryHistoryEnabled, queryHistoryEnabled: config.queryHistoryEnabled,
newValue: !query.starred, newValue: !queryHistoryItem.starred,
}); });
}; };
const toggleActiveUpdateComment = () => setActiveUpdateComment(!activeUpdateComment); const toggleActiveUpdateComment = () => setActiveUpdateComment(!activeUpdateComment);
const onUpdateComment = () => { const onUpdateComment = () => {
commentHistoryItem(query.id, comment); commentHistoryItem(queryHistoryItem.id, comment);
setActiveUpdateComment(false); setActiveUpdateComment(false);
reportInteraction('grafana_explore_query_history_commented', { reportInteraction('grafana_explore_query_history_commented', {
queryHistoryEnabled: config.queryHistoryEnabled, queryHistoryEnabled: config.queryHistoryEnabled,
@ -277,7 +278,7 @@ export function RichHistoryCard(props: Props) {
const onCancelUpdateComment = () => { const onCancelUpdateComment = () => {
setActiveUpdateComment(false); setActiveUpdateComment(false);
setComment(query.comment); setComment(queryHistoryItem.comment);
}; };
const onKeyDown = (keyEvent: React.KeyboardEvent) => { const onKeyDown = (keyEvent: React.KeyboardEvent) => {
@ -327,7 +328,7 @@ export function RichHistoryCard(props: Props) {
name="comment-alt" name="comment-alt"
onClick={toggleActiveUpdateComment} onClick={toggleActiveUpdateComment}
tooltip={ tooltip={
query.comment?.length > 0 queryHistoryItem.comment?.length > 0
? t('explore.rich-history-card.edit-comment-tooltip', 'Edit comment') ? t('explore.rich-history-card.edit-comment-tooltip', 'Edit comment')
: t('explore.rich-history-card.add-comment-tooltip', 'Add comment') : t('explore.rich-history-card.add-comment-tooltip', 'Add comment')
} }
@ -337,7 +338,7 @@ export function RichHistoryCard(props: Props) {
onClick={onCopyQuery} onClick={onCopyQuery}
tooltip={t('explore.rich-history-card.copy-query-tooltip', 'Copy query to clipboard')} tooltip={t('explore.rich-history-card.copy-query-tooltip', 'Copy query to clipboard')}
/> />
{value?.dsInstance && ( {historyCardData?.datasourceInstance && (
<IconButton <IconButton
name="share-alt" name="share-alt"
onClick={onCreateShortLink} onClick={onCreateShortLink}
@ -355,11 +356,11 @@ export function RichHistoryCard(props: Props) {
onClick={onDeleteQuery} onClick={onDeleteQuery}
/> />
<IconButton <IconButton
name={query.starred ? 'favorite' : 'star'} name={queryHistoryItem.starred ? 'favorite' : 'star'}
iconType={query.starred ? 'mono' : 'default'} iconType={queryHistoryItem.starred ? 'mono' : 'default'}
onClick={onStarrQuery} onClick={onStarrQuery}
tooltip={ tooltip={
query.starred queryHistoryItem.starred
? t('explore.rich-history-card.unstar-query-tooltip', 'Unstar query') ? t('explore.rich-history-card.unstar-query-tooltip', 'Unstar query')
: t('explore.rich-history-card.star-query-tooltip', 'Star query') : t('explore.rich-history-card.star-query-tooltip', 'Star query')
} }
@ -370,21 +371,21 @@ export function RichHistoryCard(props: Props) {
return ( return (
<div className={styles.queryCard}> <div className={styles.queryCard}>
<div className={styles.cardRow}> <div className={styles.cardRow}>
<DatasourceInfo dsApi={value?.dsInstance} size="sm" /> <DatasourceInfo dsApi={historyCardData?.datasourceInstance} size="sm" />
{queryActionButtons} {queryActionButtons}
</div> </div>
<div className={cx(styles.cardRow)}> <div className={cx(styles.cardRow)}>
<div className={styles.queryContainer}> <div className={styles.queryContainer}>
{value?.queries.map((q, i) => { {historyCardData?.queries.map((q, i) => {
return <Query query={q} key={`${q}-${i}`} showDsInfo={value?.dsInstance?.meta.mixed} />; return <Query query={q} key={`${q}-${i}`} showDsInfo={historyCardData?.datasourceInstance?.meta.mixed} />;
})} })}
{!activeUpdateComment && query.comment && ( {!activeUpdateComment && queryHistoryItem.comment && (
<div <div
aria-label={t('explore.rich-history-card.query-comment-label', 'Query comment')} aria-label={t('explore.rich-history-card.query-comment-label', 'Query comment')}
className={styles.comment} className={styles.comment}
> >
{query.comment} {queryHistoryItem.comment}
</div> </div>
)} )}
{activeUpdateComment && updateComment} {activeUpdateComment && updateComment}
@ -394,9 +395,11 @@ export function RichHistoryCard(props: Props) {
<Button <Button
variant="secondary" variant="secondary"
onClick={onRunQuery} onClick={onRunQuery}
disabled={!value?.dsInstance || value.queries.some((query) => !query.datasource)} disabled={
!historyCardData?.datasourceInstance || historyCardData.queries.some((query) => !query.datasource)
}
> >
{datasourceInstance?.uid === query.datasourceUid ? ( {datasourceInstance?.uid === queryHistoryItem.datasourceUid ? (
<Trans i18nKey="explore.rich-history-card.run-query-button">Run query</Trans> <Trans i18nKey="explore.rich-history-card.run-query-button">Run query</Trans>
) : ( ) : (
<Trans i18nKey="explore.rich-history-card.switch-datasource-button"> <Trans i18nKey="explore.rich-history-card.switch-datasource-button">

@ -262,7 +262,7 @@ export function RichHistoryQueriesTab(props: RichHistoryQueriesTabProps) {
</span> </span>
</div> </div>
{mappedQueriesToHeadings[heading].map((q) => { {mappedQueriesToHeadings[heading].map((q) => {
return <RichHistoryCard query={q} key={q.id} exploreId={exploreId} />; return <RichHistoryCard queryHistoryItem={q} key={q.id} exploreId={exploreId} />;
})} })}
</div> </div>
); );

@ -166,7 +166,7 @@ export function RichHistoryStarredTab(props: RichHistoryStarredTabProps) {
)} )}
{!loading && {!loading &&
queries.map((q) => { queries.map((q) => {
return <RichHistoryCard query={q} key={q.id} exploreId={exploreId} />; return <RichHistoryCard queryHistoryItem={q} key={q.id} exploreId={exploreId} />;
})} })}
{queries.length && queries.length !== totalQueries ? ( {queries.length && queries.length !== totalQueries ? (
<div> <div>

Loading…
Cancel
Save