Various Polish Stories (#2377)
* Add helpful tooltip to download CSV button * Expose settings and tokens in navbar * Remove gap around auto refresh dropdown * Refactor Empty state styles * Standardize tasks and dashboards empty states * Standardize resource empty states in home page * Refactor dashboard empty state * Amend * Standardize name and appearance of new dashboards and cells * Ensure pause button doesn't press up against dropdownpull/10616/head
parent
28ebc88b44
commit
c5099e7be8
|
@ -3,6 +3,8 @@
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@import 'src/style/modules';
|
||||||
|
|
||||||
.empty-state {
|
.empty-state {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -12,42 +14,59 @@
|
||||||
|
|
||||||
.empty-state--text,
|
.empty-state--text,
|
||||||
.empty-state--sub-text {
|
.empty-state--sub-text {
|
||||||
|
margin-bottom: 0;
|
||||||
|
text-align: center;
|
||||||
color: $empty-state-text;
|
color: $empty-state-text;
|
||||||
@extend %no-user-select;
|
@extend %no-user-select;
|
||||||
|
|
||||||
|
em {
|
||||||
|
font-weight: 600;
|
||||||
|
font-style: normal;
|
||||||
|
color: $empty-state-highlight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Size Modifiers
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
@mixin emptyStateSizeModifier($fontSize, $padding) {
|
||||||
|
padding: ceil($padding * 2.75) 0;
|
||||||
|
|
||||||
|
.empty-state--text,
|
||||||
|
.empty-state--sub-text {
|
||||||
|
margin-top: ceil($fontSize * 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
margin-top: $padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
> *:last-child {
|
||||||
|
margin-bottom: ceil($fontSize * 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state--text {
|
||||||
|
font-size: ceil($fontSize * 1.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state--sub-text {
|
||||||
|
font-size: $fontSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state--xs {
|
.empty-state--xs {
|
||||||
padding: $ix-marg-a 0;
|
@include emptyStateSizeModifier($form-xs-font, $ix-marg-a);
|
||||||
|
|
||||||
.empty-state--text,
|
|
||||||
.empty-state--sub-text {
|
|
||||||
margin: $ix-marg-a 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state--sm {
|
.empty-state--sm {
|
||||||
padding: $ix-marg-c 0;
|
@include emptyStateSizeModifier($form-sm-font, $ix-marg-b);
|
||||||
|
|
||||||
.empty-state--text,
|
|
||||||
.empty-state--sub-text {
|
|
||||||
margin: $ix-marg-b 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state--md {
|
.empty-state--md {
|
||||||
padding: $ix-marg-d 0;
|
@include emptyStateSizeModifier($form-md-font, $ix-marg-c);
|
||||||
|
|
||||||
.empty-state--text,
|
|
||||||
.empty-state--sub-text {
|
|
||||||
margin: $ix-marg-b 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state--lg {
|
.empty-state--lg {
|
||||||
padding: $ix-marg-f 0;
|
@include emptyStateSizeModifier($form-lg-font, $ix-marg-d);
|
||||||
|
|
||||||
.empty-state--text,
|
|
||||||
.empty-state--sub-text {
|
|
||||||
margin: $ix-marg-c 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -8,6 +8,10 @@ import EmptyStateSubText from 'src/clockface/components/empty_state/EmptyStateSu
|
||||||
// Types
|
// Types
|
||||||
import {ComponentSize} from 'src/clockface/types'
|
import {ComponentSize} from 'src/clockface/types'
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
import 'src/clockface/components/empty_state/EmptyState.scss'
|
||||||
|
|
||||||
|
// Decorators
|
||||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
|
@ -1,12 +1,38 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
import React, {SFC} from 'react'
|
import React, {SFC, Fragment} from 'react'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import uuid from 'uuid'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
text: string
|
text: string
|
||||||
|
highlightWords?: string | string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const EmptyStateText: SFC<Props> = ({text}) => (
|
const highlighter = (
|
||||||
<h4 className="empty-state--text">{text}</h4>
|
text: string,
|
||||||
|
highlightWords: string | string[]
|
||||||
|
): JSX.Element[] => {
|
||||||
|
const splitString = text.replace(/[\\][n]/g, 'LINEBREAK').split(' ')
|
||||||
|
|
||||||
|
return splitString.map(word => {
|
||||||
|
if (_.includes(highlightWords, word)) {
|
||||||
|
return <em key={uuid.v4()}>{`${word}`}</em>
|
||||||
|
}
|
||||||
|
|
||||||
|
if (word === 'LINEBREAK') {
|
||||||
|
return <br />
|
||||||
|
}
|
||||||
|
|
||||||
|
if (word === 'SPACECHAR') {
|
||||||
|
return <Fragment key={uuid.v4()}> </Fragment>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Fragment key={uuid.v4()}>{`${word} `}</Fragment>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const EmptyStateText: SFC<Props> = ({text, highlightWords}) => (
|
||||||
|
<h4 className="empty-state--text">{highlighter(text, highlightWords)}</h4>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default EmptyStateText
|
export default EmptyStateText
|
||||||
|
|
|
@ -23,6 +23,7 @@ interface Props {
|
||||||
onPositionChange: (cells: Cell[]) => void
|
onPositionChange: (cells: Cell[]) => void
|
||||||
setScrollTop: (e: MouseEvent<HTMLElement>) => void
|
setScrollTop: (e: MouseEvent<HTMLElement>) => void
|
||||||
onEditView: (viewID: string) => void
|
onEditView: (viewID: string) => void
|
||||||
|
onAddCell: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@ErrorHandling
|
@ErrorHandling
|
||||||
|
@ -40,6 +41,7 @@ class DashboardComponent extends PureComponent<Props> {
|
||||||
onPositionChange,
|
onPositionChange,
|
||||||
inPresentationMode,
|
inPresentationMode,
|
||||||
setScrollTop,
|
setScrollTop,
|
||||||
|
onAddCell,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -63,7 +65,7 @@ class DashboardComponent extends PureComponent<Props> {
|
||||||
onEditView={onEditView}
|
onEditView={onEditView}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<DashboardEmpty dashboard={dashboard} />
|
<DashboardEmpty onAddCell={onAddCell} />
|
||||||
)}
|
)}
|
||||||
{/* This element is used as a portal container for note tooltips in cell headers */}
|
{/* This element is used as a portal container for note tooltips in cell headers */}
|
||||||
<div className="cell-header-note-tooltip-container" />
|
<div className="cell-header-note-tooltip-container" />
|
||||||
|
|
|
@ -10,6 +10,12 @@ import GraphTips from 'src/shared/components/graph_tips/GraphTips'
|
||||||
import RenamablePageTitle from 'src/pageLayout/components/RenamablePageTitle'
|
import RenamablePageTitle from 'src/pageLayout/components/RenamablePageTitle'
|
||||||
import {Button, ButtonShape, ComponentColor, IconFont} from 'src/clockface'
|
import {Button, ButtonShape, ComponentColor, IconFont} from 'src/clockface'
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
import {
|
||||||
|
DEFAULT_DASHBOARD_NAME,
|
||||||
|
DASHBOARD_NAME_MAX_LENGTH,
|
||||||
|
} from 'src/dashboards/constants/index'
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
import {addNote} from 'src/dashboards/actions/v2/notes'
|
import {addNote} from 'src/dashboards/actions/v2/notes'
|
||||||
|
|
||||||
|
@ -122,8 +128,10 @@ class DashboardHeader extends Component<Props> {
|
||||||
if (dashboard) {
|
if (dashboard) {
|
||||||
return (
|
return (
|
||||||
<RenamablePageTitle
|
<RenamablePageTitle
|
||||||
|
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
||||||
onRename={onRenameDashboard}
|
onRename={onRenameDashboard}
|
||||||
name={activeDashboard}
|
name={activeDashboard}
|
||||||
|
placeholder={DEFAULT_DASHBOARD_NAME}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,6 +213,7 @@ class DashboardPage extends Component<Props, State> {
|
||||||
onPositionChange={this.handlePositionChange}
|
onPositionChange={this.handlePositionChange}
|
||||||
onDeleteCell={this.handleDeleteDashboardCell}
|
onDeleteCell={this.handleDeleteDashboardCell}
|
||||||
onEditView={this.handleEditView}
|
onEditView={this.handleEditView}
|
||||||
|
onAddCell={this.handleAddCell}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<OverlayTechnology visible={isShowingVEO}>
|
<OverlayTechnology visible={isShowingVEO}>
|
||||||
|
|
|
@ -12,6 +12,12 @@ import {
|
||||||
} from 'src/clockface'
|
} from 'src/clockface'
|
||||||
import {Page} from 'src/pageLayout'
|
import {Page} from 'src/pageLayout'
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
import {
|
||||||
|
DEFAULT_CELL_NAME,
|
||||||
|
CELL_NAME_MAX_LENGTH,
|
||||||
|
} from 'src/dashboards/constants/index'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
name: string
|
name: string
|
||||||
onSetName: (name: string) => void
|
onSetName: (name: string) => void
|
||||||
|
@ -27,7 +33,12 @@ class VEOHeader extends PureComponent<Props> {
|
||||||
<div className="veo-header">
|
<div className="veo-header">
|
||||||
<Page.Header fullWidth={true}>
|
<Page.Header fullWidth={true}>
|
||||||
<Page.Header.Left>
|
<Page.Header.Left>
|
||||||
<RenamablePageTitle name={name} onRename={onSetName} />
|
<RenamablePageTitle
|
||||||
|
name={name}
|
||||||
|
onRename={onSetName}
|
||||||
|
placeholder={DEFAULT_CELL_NAME}
|
||||||
|
maxLength={CELL_NAME_MAX_LENGTH}
|
||||||
|
/>
|
||||||
</Page.Header.Left>
|
</Page.Header.Left>
|
||||||
<Page.Header.Right>
|
<Page.Header.Right>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -1,51 +1,45 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
import React, {Component} from 'react'
|
import React, {Component} from 'react'
|
||||||
import {connect} from 'react-redux'
|
|
||||||
|
|
||||||
// Actions
|
// Components
|
||||||
import {addCellAsync} from 'src/dashboards/actions/v2'
|
import {
|
||||||
|
Button,
|
||||||
// Types
|
IconFont,
|
||||||
import {Dashboard} from 'src/api'
|
ComponentColor,
|
||||||
|
EmptyState,
|
||||||
|
ComponentSize,
|
||||||
|
} from 'src/clockface'
|
||||||
|
|
||||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
dashboard: Dashboard
|
onAddCell: () => void
|
||||||
}
|
|
||||||
|
|
||||||
interface Actions {
|
|
||||||
addDashboardCell: typeof addCellAsync
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ErrorHandling
|
@ErrorHandling
|
||||||
class DashboardEmpty extends Component<Props & Actions> {
|
class DashboardEmpty extends Component<Props> {
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
}
|
|
||||||
|
|
||||||
public handleAddCell = __ => async () => {
|
|
||||||
const {dashboard, addDashboardCell} = this.props
|
|
||||||
await addDashboardCell(dashboard)
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
const {onAddCell} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dashboard-empty">
|
<div className="dashboard-empty">
|
||||||
<p>
|
<EmptyState size={ComponentSize.Large}>
|
||||||
This Dashboard doesn't have any <strong>Cells</strong>, why not add
|
<EmptyState.Text
|
||||||
one?
|
text="This Dashboard doesn't have any Cells , why not add
|
||||||
</p>
|
one?"
|
||||||
|
highlightWords={['Cells']}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
text="Add Cell"
|
||||||
|
size={ComponentSize.Medium}
|
||||||
|
icon={IconFont.AddCell}
|
||||||
|
color={ComponentColor.Primary}
|
||||||
|
onClick={onAddCell}
|
||||||
|
/>
|
||||||
|
</EmptyState>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mdtp = {
|
export default DashboardEmpty
|
||||||
addDashboardCell: addCellAsync,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
null,
|
|
||||||
mdtp
|
|
||||||
)(DashboardEmpty)
|
|
||||||
|
|
|
@ -40,6 +40,9 @@ import {
|
||||||
dashboardCreateFailed,
|
dashboardCreateFailed,
|
||||||
} from 'src/shared/copy/notifications'
|
} from 'src/shared/copy/notifications'
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
import {DEFAULT_DASHBOARD_NAME} from 'src/dashboards/constants/index'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {Notification} from 'src/types/notifications'
|
import {Notification} from 'src/types/notifications'
|
||||||
import {DashboardFile} from 'src/types/v2/dashboards'
|
import {DashboardFile} from 'src/types/v2/dashboards'
|
||||||
|
@ -152,7 +155,7 @@ class DashboardIndex extends PureComponent<Props, State> {
|
||||||
const {router, notify} = this.props
|
const {router, notify} = this.props
|
||||||
try {
|
try {
|
||||||
const newDashboard = {
|
const newDashboard = {
|
||||||
name: 'Name this dashboard',
|
name: DEFAULT_DASHBOARD_NAME,
|
||||||
cells: [],
|
cells: [],
|
||||||
}
|
}
|
||||||
const data = await createDashboard(newDashboard)
|
const data = await createDashboard(newDashboard)
|
||||||
|
@ -215,7 +218,7 @@ class DashboardIndex extends PureComponent<Props, State> {
|
||||||
h: 4,
|
h: 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = _.get(dashboard, 'name', 'Name this dashboard')
|
const name = _.get(dashboard, 'name', DEFAULT_DASHBOARD_NAME)
|
||||||
const cellsWithDefaultsApplied = getDeep<Cell[]>(
|
const cellsWithDefaultsApplied = getDeep<Cell[]>(
|
||||||
dashboard,
|
dashboard,
|
||||||
'cells',
|
'cells',
|
||||||
|
|
|
@ -141,19 +141,23 @@ class DashboardsTable extends PureComponent<Props & WithRouterProps, State> {
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
return (
|
return (
|
||||||
<EmptyState size={ComponentSize.Large}>
|
<EmptyState size={ComponentSize.Large}>
|
||||||
<EmptyState.Text text="No dashboards match your search term" />
|
<EmptyState.Text text="No Dashboards match your search term" />
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EmptyState size={ComponentSize.Large}>
|
<EmptyState size={ComponentSize.Large}>
|
||||||
<EmptyState.Text text="Looks like you don’t have any dashboards" />
|
<EmptyState.Text
|
||||||
|
text="Looks like you don’t have any Dashboards , why not create one?"
|
||||||
|
highlightWords={['Dashboards']}
|
||||||
|
/>
|
||||||
<Button
|
<Button
|
||||||
text="Create a Dashboard"
|
text="Create a Dashboard"
|
||||||
icon={IconFont.Plus}
|
icon={IconFont.Plus}
|
||||||
color={ComponentColor.Primary}
|
color={ComponentColor.Primary}
|
||||||
onClick={onCreateDashboard}
|
onClick={onCreateDashboard}
|
||||||
|
size={ComponentSize.Medium}
|
||||||
/>
|
/>
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
)
|
)
|
||||||
|
|
|
@ -86,6 +86,7 @@ type NewDefaultDashboard = Pick<
|
||||||
cells: NewDefaultCell[]
|
cells: NewDefaultCell[]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
export const DEFAULT_CELL_NAME = 'Name this Cell'
|
||||||
export const DEFAULT_DASHBOARD_NAME = 'Name this Dashboard'
|
export const DEFAULT_DASHBOARD_NAME = 'Name this Dashboard'
|
||||||
export const NEW_DASHBOARD: NewDefaultDashboard = {
|
export const NEW_DASHBOARD: NewDefaultDashboard = {
|
||||||
name: DEFAULT_DASHBOARD_NAME,
|
name: DEFAULT_DASHBOARD_NAME,
|
||||||
|
@ -96,6 +97,7 @@ export const TYPE_QUERY_CONFIG: string = 'queryConfig'
|
||||||
export const TYPE_SHIFTED: string = 'shifted queryConfig'
|
export const TYPE_SHIFTED: string = 'shifted queryConfig'
|
||||||
export const TYPE_FLUX: string = 'flux'
|
export const TYPE_FLUX: string = 'flux'
|
||||||
export const DASHBOARD_NAME_MAX_LENGTH: number = 50
|
export const DASHBOARD_NAME_MAX_LENGTH: number = 50
|
||||||
|
export const CELL_NAME_MAX_LENGTH: number = 68
|
||||||
|
|
||||||
export enum CEOTabs {
|
export enum CEOTabs {
|
||||||
Queries = 'Queries',
|
Queries = 'Queries',
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
import React, {PureComponent} from 'react'
|
import React, {PureComponent} from 'react'
|
||||||
import {Link} from 'react-router'
|
import {Link} from 'react-router'
|
||||||
|
|
||||||
|
// Components
|
||||||
|
import {EmptyState, ComponentSize} from 'src/clockface'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {Dashboard} from 'src/types'
|
import {Dashboard} from 'src/types'
|
||||||
|
|
||||||
|
@ -12,8 +15,13 @@ interface Props {
|
||||||
export default class UserDashboardList extends PureComponent<Props> {
|
export default class UserDashboardList extends PureComponent<Props> {
|
||||||
public render() {
|
public render() {
|
||||||
const {dashboards} = this.props
|
const {dashboards} = this.props
|
||||||
|
|
||||||
if (this.isEmpty) {
|
if (this.isEmpty) {
|
||||||
return <div>Looks like you dont have any dashboards</div>
|
return (
|
||||||
|
<EmptyState size={ComponentSize.ExtraSmall}>
|
||||||
|
<EmptyState.Text text="You don't have any Dashboards" />
|
||||||
|
</EmptyState>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
import React, {PureComponent} from 'react'
|
import React, {PureComponent} from 'react'
|
||||||
import {Link} from 'react-router'
|
import {Link} from 'react-router'
|
||||||
|
|
||||||
|
// Components
|
||||||
|
import {EmptyState, ComponentSize} from 'src/clockface'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {Organization} from 'src/types/v2'
|
import {Organization} from 'src/types/v2'
|
||||||
|
|
||||||
|
@ -14,7 +17,11 @@ export default class UserDashboardList extends PureComponent<Props> {
|
||||||
const {orgs} = this.props
|
const {orgs} = this.props
|
||||||
|
|
||||||
if (this.isEmpty) {
|
if (this.isEmpty) {
|
||||||
return <div>Looks like you dont belong to any organizations</div>
|
return (
|
||||||
|
<EmptyState size={ComponentSize.ExtraSmall}>
|
||||||
|
<EmptyState.Text text="You don't belong to any Organizations" />
|
||||||
|
</EmptyState>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -6,12 +6,6 @@ import classnames from 'classnames'
|
||||||
import {Input} from 'src/clockface'
|
import {Input} from 'src/clockface'
|
||||||
import {ClickOutside} from 'src/shared/components/ClickOutside'
|
import {ClickOutside} from 'src/shared/components/ClickOutside'
|
||||||
|
|
||||||
// Constants
|
|
||||||
import {
|
|
||||||
DASHBOARD_NAME_MAX_LENGTH,
|
|
||||||
DEFAULT_DASHBOARD_NAME,
|
|
||||||
} from 'src/dashboards/constants/index'
|
|
||||||
|
|
||||||
// Decorators
|
// Decorators
|
||||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
|
|
||||||
|
@ -21,6 +15,8 @@ import 'src/pageLayout/components/RenamablePageTitle.scss'
|
||||||
interface Props {
|
interface Props {
|
||||||
onRename: (name: string) => void
|
onRename: (name: string) => void
|
||||||
name: string
|
name: string
|
||||||
|
placeholder: string
|
||||||
|
maxLength: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
@ -41,7 +37,7 @@ class RenamablePageTitle extends Component<Props, State> {
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {isEditing} = this.state
|
const {isEditing} = this.state
|
||||||
const {name} = this.props
|
const {name, placeholder} = this.props
|
||||||
|
|
||||||
if (isEditing) {
|
if (isEditing) {
|
||||||
return (
|
return (
|
||||||
|
@ -56,7 +52,7 @@ class RenamablePageTitle extends Component<Props, State> {
|
||||||
return (
|
return (
|
||||||
<div className="renamable-page-title">
|
<div className="renamable-page-title">
|
||||||
<div className={this.titleClassName} onClick={this.handleStartEditing}>
|
<div className={this.titleClassName} onClick={this.handleStartEditing}>
|
||||||
{name || DEFAULT_DASHBOARD_NAME}
|
{name || placeholder}
|
||||||
<span className="icon pencil" />
|
<span className="icon pencil" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,14 +60,15 @@ class RenamablePageTitle extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private get input(): JSX.Element {
|
private get input(): JSX.Element {
|
||||||
|
const {placeholder, maxLength} = this.props
|
||||||
const {workingName} = this.state
|
const {workingName} = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
maxLength={maxLength}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
placeholder={DEFAULT_DASHBOARD_NAME}
|
placeholder={placeholder}
|
||||||
onFocus={this.handleInputFocus}
|
onFocus={this.handleInputFocus}
|
||||||
onChange={this.handleInputChange}
|
onChange={this.handleInputChange}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
|
@ -119,9 +116,9 @@ class RenamablePageTitle extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private get titleClassName(): string {
|
private get titleClassName(): string {
|
||||||
const {name} = this.props
|
const {name, placeholder} = this.props
|
||||||
|
|
||||||
const nameIsUntitled = name === DEFAULT_DASHBOARD_NAME || name === ''
|
const nameIsUntitled = name === placeholder || name === ''
|
||||||
|
|
||||||
return classnames('renamable-page-title--title', {
|
return classnames('renamable-page-title--title', {
|
||||||
untitled: nameIsUntitled,
|
untitled: nameIsUntitled,
|
||||||
|
|
|
@ -45,6 +45,18 @@ class SideNav extends PureComponent<Props> {
|
||||||
location={location.pathname}
|
location={location.pathname}
|
||||||
highlightWhen={['me', 'account']}
|
highlightWhen={['me', 'account']}
|
||||||
>
|
>
|
||||||
|
<NavMenu.SubItem
|
||||||
|
title="Settings"
|
||||||
|
link="/account/settings"
|
||||||
|
location={location.pathname}
|
||||||
|
highlightWhen={['settings']}
|
||||||
|
/>
|
||||||
|
<NavMenu.SubItem
|
||||||
|
title="Tokens"
|
||||||
|
link="/account/tokens"
|
||||||
|
location={location.pathname}
|
||||||
|
highlightWhen={['tokens']}
|
||||||
|
/>
|
||||||
<NavMenu.SubItem
|
<NavMenu.SubItem
|
||||||
title="Logout"
|
title="Logout"
|
||||||
link="/logout"
|
link="/logout"
|
||||||
|
|
|
@ -14,18 +14,37 @@ interface Props {
|
||||||
|
|
||||||
class CSVExportButton extends PureComponent<Props, {}> {
|
class CSVExportButton extends PureComponent<Props, {}> {
|
||||||
public render() {
|
public render() {
|
||||||
const {files} = this.props
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
titleText={this.titleText}
|
||||||
text="CSV"
|
text="CSV"
|
||||||
icon={IconFont.Download}
|
icon={IconFont.Download}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
status={files ? ComponentStatus.Default : ComponentStatus.Disabled}
|
status={this.buttonStatus}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get buttonStatus(): ComponentStatus {
|
||||||
|
const {files} = this.props
|
||||||
|
|
||||||
|
if (files) {
|
||||||
|
return ComponentStatus.Default
|
||||||
|
}
|
||||||
|
|
||||||
|
return ComponentStatus.Disabled
|
||||||
|
}
|
||||||
|
|
||||||
|
private get titleText(): string {
|
||||||
|
const {files} = this.props
|
||||||
|
|
||||||
|
if (files) {
|
||||||
|
return 'Download query results as a .CSV file'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Create a query in order to download results as .CSV'
|
||||||
|
}
|
||||||
|
|
||||||
private handleClick = () => {
|
private handleClick = () => {
|
||||||
const {files} = this.props
|
const {files} = this.props
|
||||||
const csv = files.join('\n\n')
|
const csv = files.join('\n\n')
|
||||||
|
|
|
@ -3,15 +3,17 @@
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@import 'src/style/modules';
|
||||||
|
|
||||||
.autorefresh-dropdown {
|
.autorefresh-dropdown {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
.dropdown {
|
|
||||||
margin-right: $ix-marg-a;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.paused .dropdown--selected {
|
&.paused .dropdown--selected {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.autorefresh-dropdown--pause {
|
||||||
|
margin-left: $ix-marg-a;
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ import autoRefreshOptions, {
|
||||||
AutoRefreshOptionType,
|
AutoRefreshOptionType,
|
||||||
} from 'src/shared/data/autoRefreshes'
|
} from 'src/shared/data/autoRefreshes'
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
import 'src/shared/components/dropdown_auto_refresh/AutoRefreshDropdown.scss'
|
||||||
|
|
||||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -123,6 +126,7 @@ class AutoRefreshDropdown extends Component<Props> {
|
||||||
shape={ButtonShape.Square}
|
shape={ButtonShape.Square}
|
||||||
icon={IconFont.Refresh}
|
icon={IconFont.Refresh}
|
||||||
onClick={onManualRefresh}
|
onClick={onManualRefresh}
|
||||||
|
customClass="autorefresh-dropdown--pause"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,11 @@ import {
|
||||||
DEFAULT_GAUGE_COLORS,
|
DEFAULT_GAUGE_COLORS,
|
||||||
DEFAULT_THRESHOLDS_LIST_COLORS,
|
DEFAULT_THRESHOLDS_LIST_COLORS,
|
||||||
} from 'src/shared/constants/thresholds'
|
} from 'src/shared/constants/thresholds'
|
||||||
|
import {DEFAULT_CELL_NAME} from 'src/dashboards/constants/index'
|
||||||
|
|
||||||
function defaultView() {
|
function defaultView() {
|
||||||
return {
|
return {
|
||||||
name: 'Untitled',
|
name: DEFAULT_CELL_NAME,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,7 @@ $form-lg-font: 17px;
|
||||||
|
|
||||||
/* Empty State */
|
/* Empty State */
|
||||||
$empty-state-text: $g9-mountain;
|
$empty-state-text: $g9-mountain;
|
||||||
|
$empty-state-highlight: $g13-mist;
|
||||||
|
|
||||||
$default-font: 'Roboto', Helvetica, sans-serif;
|
$default-font: 'Roboto', Helvetica, sans-serif;
|
||||||
$code-font: 'RobotoMono', monospace;
|
$code-font: 'RobotoMono', monospace;
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
// Components
|
// Components
|
||||||
// TODO: Import these styles into their respective components instead of this stylesheet
|
// TODO: Import these styles into their respective components instead of this stylesheet
|
||||||
@import 'src/shared/components/ColorDropdown';
|
@import 'src/shared/components/ColorDropdown';
|
||||||
@import 'src/shared/components/dropdown_auto_refresh/AutoRefreshDropdown';
|
|
||||||
@import 'src/shared/components/avatar/Avatar';
|
@import 'src/shared/components/avatar/Avatar';
|
||||||
@import 'src/shared/components/tables/TableGraphs';
|
@import 'src/shared/components/tables/TableGraphs';
|
||||||
@import 'src/shared/components/fancy_scrollbar/FancyScrollbar';
|
@import 'src/shared/components/fancy_scrollbar/FancyScrollbar';
|
||||||
|
|
|
@ -34,10 +34,11 @@ export default class EmptyTasksLists extends PureComponent<Props> {
|
||||||
return (
|
return (
|
||||||
<EmptyState size={ComponentSize.Large}>
|
<EmptyState size={ComponentSize.Large}>
|
||||||
<EmptyState.Text
|
<EmptyState.Text
|
||||||
text={"Looks like you don't have any Tasks, why not create one?"}
|
text={"Looks like you don't have any Tasks , why not create one?"}
|
||||||
|
highlightWords={['Tasks']}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
size={ComponentSize.Small}
|
size={ComponentSize.Medium}
|
||||||
color={ComponentColor.Primary}
|
color={ComponentColor.Primary}
|
||||||
icon={IconFont.Plus}
|
icon={IconFont.Plus}
|
||||||
text="Create Task"
|
text="Create Task"
|
||||||
|
@ -49,7 +50,7 @@ export default class EmptyTasksLists extends PureComponent<Props> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EmptyState size={ComponentSize.Large}>
|
<EmptyState size={ComponentSize.Large}>
|
||||||
<EmptyState.Text text={'No tasks match your search term'} />
|
<EmptyState.Text text={'No Tasks match your search term'} />
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue