Skip to content

Commit

Permalink
feat(welcome): add SQL snippets to saved queries card (#11678)
Browse files Browse the repository at this point in the history
* update savedqueries card to new layout

* update card

* update card to latest mock

* update empty state

* remove fallback

* fix query statement

* update card styles

* remove double import

* use fallbackurl prop for emptystate

* update line lenth

* Update superset-frontend/src/views/CRUD/welcome/SavedQueries.tsx

Co-authored-by: Evan Rusackas <evan@preset.io>

* update styles and svg

Co-authored-by: Evan Rusackas <evan@preset.io>
  • Loading branch information
pkdotson and rusackas authored Nov 30, 2020
1 parent a4f4425 commit 0e9898c
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 50 deletions.
25 changes: 25 additions & 0 deletions superset-frontend/images/empty-query.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions superset-frontend/src/components/ListViewCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ const SkeletonActions = styled(Skeleton.Button)`

const paragraphConfig = { rows: 1, width: 150 };
interface CardProps {
title: React.ReactNode;
title?: React.ReactNode;
url?: string;
imgURL?: string;
imgFallbackURL?: string;
Expand All @@ -155,7 +155,7 @@ interface CardProps {
titleRight?: React.ReactNode;
coverLeft?: React.ReactNode;
coverRight?: React.ReactNode;
actions: React.ReactNode | null;
actions?: React.ReactNode | null;
rows?: number | string;
avatar?: string;
cover?: React.ReactNode | null;
Expand Down
15 changes: 4 additions & 11 deletions superset-frontend/src/views/CRUD/data/query/QueryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import React, { useMemo, useState, useCallback } from 'react';
import { SupersetClient, t, styled } from '@superset-ui/core';
import moment from 'moment';

import { createErrorHandler } from 'src/views/CRUD/utils';
import { createErrorHandler, shortenSQL } from 'src/views/CRUD/utils';
import withToasts from 'src/messageToasts/enhancers/withToasts';
import { useListViewResource } from 'src/views/CRUD/hooks';
import SubMenu, { SubMenuProps } from 'src/components/Menu/SubMenu';
Expand All @@ -38,6 +38,7 @@ import { QueryObject } from 'src/views/CRUD/types';
import QueryPreviewModal from './QueryPreviewModal';

const PAGE_SIZE = 25;
const SQL_PREVIEW_MAX_LINES = 4;

const TopAlignedListView = styled(ListView)<ListViewProps<QueryObject>>`
table .table-cell {
Expand All @@ -52,15 +53,7 @@ const StyledSyntaxHighlighter = styled(SyntaxHighlighter)`
text-overflow: ellipsis;
white-space: nowrap;
`;
const SQL_PREVIEW_MAX_LINES = 4;
function shortenSQL(sql: string) {
let lines: string[] = sql.split('\n');
if (lines.length >= SQL_PREVIEW_MAX_LINES) {
lines = lines.slice(0, SQL_PREVIEW_MAX_LINES);
lines.push('...');
}
return lines.join('\n');
}

interface QueryListProps {
addDangerToast: (msg: string, config?: any) => any;
addSuccessToast: (msg: string, config?: any) => any;
Expand Down Expand Up @@ -298,7 +291,7 @@ function QueryList({ addDangerToast, addSuccessToast }: QueryListProps) {
onClick={() => setQueryCurrentlyPreviewing(original)}
>
<StyledSyntaxHighlighter language="sql" style={github}>
{shortenSQL(original.sql)}
{shortenSQL(original.sql, SQL_PREVIEW_MAX_LINES)}
</StyledSyntaxHighlighter>
</div>
);
Expand Down
17 changes: 13 additions & 4 deletions superset-frontend/src/views/CRUD/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -264,22 +264,31 @@ export function handleDashboardDelete(
);
}

export function shortenSQL(sql: string, maxLines: number) {
let lines: string[] = sql.split('\n');
if (lines.length >= maxLines) {
lines = lines.slice(0, maxLines);
lines.push('...');
}
return lines.join('\n');
}

const breakpoints = [576, 768, 992, 1200];
export const mq = breakpoints.map(bp => `@media (max-width: ${bp}px)`);

export const CardContainer = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(31%, max-content));
grid-template-columns: repeat(auto-fit, minmax(31%, 31%));
${[mq[3]]} {
grid-template-columns: repeat(auto-fit, minmax(31%, max-content));
grid-template-columns: repeat(auto-fit, minmax(31%, 31%));
}
${[mq[2]]} {
grid-template-columns: repeat(auto-fit, minmax(48%, max-content));
grid-template-columns: repeat(auto-fit, minmax(48%, 48%));
}
${[mq[1]]} {
grid-template-columns: repeat(auto-fit, minmax(50%, max-content));
grid-template-columns: repeat(auto-fit, minmax(50%, 80%));
}
grid-gap: ${({ theme }) => theme.gridUnit * 8}px;
justify-content: left;
Expand Down
120 changes: 87 additions & 33 deletions superset-frontend/src/views/CRUD/welcome/SavedQueries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
*/
import React, { useState } from 'react';
import { t, SupersetClient, styled } from '@superset-ui/core';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/cjs/light';
import sql from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql';
import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github';
import withToasts from 'src/messageToasts/enhancers/withToasts';
import { Dropdown, Menu } from 'src/common/components';
import { useListViewResource, copyQueryLink } from 'src/views/CRUD/hooks';
Expand All @@ -30,9 +33,11 @@ import {
IconContainer,
CardContainer,
createErrorHandler,
CardStyles,
shortenSQL,
} from '../utils';

SyntaxHighlighter.registerLanguage('sql', sql);

const PAGE_SIZE = 3;

interface Query {
Expand All @@ -45,6 +50,8 @@ interface Query {
description?: string;
end_time?: string;
label?: string;
changed_on_delta_humanized?: string;
sql?: string | null;
}

interface SavedQueriesProps {
Expand All @@ -57,19 +64,51 @@ interface SavedQueriesProps {
mine: Array<Query>;
}

export const CardStyles = styled.div`
cursor: pointer;
a {
text-decoration: none;
}
.ant-card-cover {
border-bottom: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
& > div {
height: 171px;
}
}
.gradient-container > div {
background-size: contain;
background-repeat: no-repeat;
background-position: center;
background-color: ${({ theme }) => theme.colors.secondary.light3};
display: inline-block;
width: 100%;
height: 179px;
background-repeat: no-repeat;
vertical-align: middle;
}
`;

const QueryData = styled.div`
display: flex;
flex-direction: row;
justify-content: flex-start;
border-bottom: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
.title {
font-weight: ${({ theme }) => theme.typography.weights.normal};
color: ${({ theme }) => theme.colors.grayscale.light1};
svg {
margin-left: ${({ theme }) => theme.gridUnit * 10}px;
}
.holder {
margin: ${({ theme }) => theme.gridUnit * 2}px;
.query-title {
padding: ${({ theme }) => theme.gridUnit * 2 + 2}px;
font-size: ${({ theme }) => theme.typography.sizes.l}px;
}
`;

const QueryContainer = styled.div`
pre {
height: ${({ theme }) => theme.gridUnit * 40}px;
border: none !important;
background-color: ${({ theme }) =>
theme.colors.grayscale.light5} !important;
overflow: hidden;
padding: ${({ theme }) => theme.gridUnit * 4}px !important;
}
`;

const SavedQueries = ({
user,
addDangerToast,
Expand Down Expand Up @@ -259,35 +298,50 @@ const SavedQueries = ({
key={q.id}
>
<ListViewCard
imgFallbackURL=""
imgURL=""
url={`/superset/sqllab?savedQueryId=${q.id}`}
title={q.label}
rows={q.rows}
description={t('Last run ', q.end_time)}
imgFallbackURL="/static/assets/images/empty-query.svg"
description={t('Last run %s', q.changed_on_delta_humanized)}
cover={
<QueryData>
<div className="holder">
<div className="title">{t('Tables')}</div>
<div>{q?.sql_tables?.length}</div>
</div>
<div className="holder">
<div className="title">{t('Datasource Name')}</div>
<div>{q?.sql_tables && q.sql_tables[0]?.table}</div>
</div>
</QueryData>
q?.sql?.length ? (
<QueryContainer>
<SyntaxHighlighter
language="sql"
lineProps={{
style: {
color: 'black',
wordBreak: 'break-all',
whiteSpace: 'pre-wrap',
},
}}
style={github}
wrapLines
lineNumberStyle={{
display: 'none',
}}
showLineNumbers={false}
>
{shortenSQL(q.sql, 25)}
</SyntaxHighlighter>
</QueryContainer>
) : (
false
)
}
actions={
<ListViewCard.Actions
onClick={e => {
e.stopPropagation();
e.preventDefault();
}}
>
<Dropdown overlay={renderMenu(q)}>
<Icon name="more-horiz" />
</Dropdown>
</ListViewCard.Actions>
<QueryData>
<ListViewCard.Actions
onClick={e => {
e.stopPropagation();
e.preventDefault();
}}
>
<Dropdown overlay={renderMenu(q)}>
<Icon name="more-horiz" />
</Dropdown>
</ListViewCard.Actions>
</QueryData>
}
/>
</CardStyles>
Expand Down

0 comments on commit 0e9898c

Please sign in to comment.