Merge branch 'feat/dashboards-container-org' of github.com:influxdata/influxdb into feat/dashboards-container-org

pull/11775/head
Palak Bhojani 2019-02-08 10:59:41 -08:00
commit 5655a06be2
17 changed files with 251 additions and 239 deletions

View File

@ -15,9 +15,8 @@
1. [11700](https://github.com/influxdata/influxdb/pull/11700): Update Tasks tab on Org page to look like Tasks Page
1. [11740](https://github.com/influxdata/influxdb/pull/11740): Add view button to view the telegraf config toml
1. [11522](https://github.com/influxdata/influxdb/pull/11522): Add plugin information step to allow for config naming and configure one plugin at a time
### Bug Fixes
1. [11758](https://github.com/influxdata/influxdb/pull/11758): Update Dashboards tab on Org page to look like Dashboards Page
## Bug Fixes
1. [11678](https://github.com/influxdata/influxdb/pull/11678): Update the System Telegraf Plugin bundle to include the swap plugin
1. [11722](https://github.com/influxdata/influxdb/pull/11722): Revert behavior allowing users to create authorizations on behalf of another user

View File

@ -207,9 +207,3 @@
.index-list--row-cell .index-list--cell a {
white-space: nowrap;
}
.index-list--resource-name {
margin-left: 6px;
margin-right: $ix-marg-a + $ix-marg-b;
font-size: 17px;
}

View File

@ -6,7 +6,7 @@ import {downloadTextFile} from 'src/shared/utils/download'
import _ from 'lodash'
// Components
import DashboardsContents from 'src/dashboards/components/dashboard_index/Contents'
import DashboardsIndexContents from 'src/dashboards/components/dashboard_index/DashboardsIndexContents'
import {Page} from 'src/pageLayout'
import SearchWidget from 'src/shared/components/search_widget/SearchWidget'
import {
@ -132,20 +132,23 @@ class DashboardIndex extends PureComponent<Props, State> {
</Page.Header.Right>
</Page.Header>
<Page.Contents fullWidth={false} scrollable={true}>
<DashboardsContents
dashboards={dashboards}
orgs={orgs}
onSetDefaultDashboard={this.handleSetDefaultDashboard}
defaultDashboardLink={links.defaultDashboard}
onDeleteDashboard={this.handleDeleteDashboard}
onCreateDashboard={this.handleCreateDashboard}
onCloneDashboard={this.handleCloneDashboard}
onExportDashboard={this.handleExportDashboard}
onUpdateDashboard={handleUpdateDashboard}
onEditLabels={this.handleStartEditingLabels}
notify={notify}
searchTerm={searchTerm}
/>
<div className="col-md-12">
<DashboardsIndexContents
dashboards={dashboards}
orgs={orgs}
onSetDefaultDashboard={this.handleSetDefaultDashboard}
defaultDashboardLink={links.defaultDashboard}
onDeleteDashboard={this.handleDeleteDashboard}
onCreateDashboard={this.handleCreateDashboard}
onCloneDashboard={this.handleCloneDashboard}
onExportDashboard={this.handleExportDashboard}
onUpdateDashboard={handleUpdateDashboard}
onEditLabels={this.handleStartEditingLabels}
notify={notify}
searchTerm={searchTerm}
showOwnerColumn={true}
/>
</div>
</Page.Contents>
</Page>
{this.renderImportOverlay}

View File

@ -25,7 +25,7 @@ interface Props {
onEditLabels: (dashboard: Dashboard) => void
notify: (message: Notification) => void
searchTerm: string
showInlineEdit?: boolean
showOwnerColumn: boolean
}
@ErrorHandling
@ -42,26 +42,24 @@ export default class DashboardsIndexContents extends Component<Props> {
onEditLabels,
searchTerm,
orgs,
showInlineEdit,
showOwnerColumn,
} = this.props
return (
<div className="col-md-12">
<Table
searchTerm={searchTerm}
dashboards={this.filteredDashboards}
onDeleteDashboard={onDeleteDashboard}
onCreateDashboard={onCreateDashboard}
onCloneDashboard={onCloneDashboard}
onExportDashboard={onExportDashboard}
defaultDashboardLink={defaultDashboardLink}
onSetDefaultDashboard={onSetDefaultDashboard}
onUpdateDashboard={onUpdateDashboard}
onEditLabels={onEditLabels}
orgs={orgs}
showInlineEdit={showInlineEdit}
/>
</div>
<Table
searchTerm={searchTerm}
dashboards={this.filteredDashboards}
onDeleteDashboard={onDeleteDashboard}
onCreateDashboard={onCreateDashboard}
onCloneDashboard={onCloneDashboard}
onExportDashboard={onExportDashboard}
defaultDashboardLink={defaultDashboardLink}
onSetDefaultDashboard={onSetDefaultDashboard}
onUpdateDashboard={onUpdateDashboard}
onEditLabels={onEditLabels}
orgs={orgs}
showOwnerColumn={showOwnerColumn}
/>
)
}

View File

@ -20,6 +20,10 @@ import SortingHat from 'src/shared/components/sorting_hat/SortingHat'
import {Sort} from 'src/clockface'
import {Dashboard, Organization} from 'src/types/v2'
// Constants
const OWNER_COL_WIDTH = 17
const NAME_COL_WIDTH = 63
interface Props {
searchTerm: string
dashboards: Dashboard[]
@ -32,7 +36,7 @@ interface Props {
onSetDefaultDashboard: (dashboardLink: string) => void
onEditLabels: (dashboard: Dashboard) => void
orgs: Organization[]
showInlineEdit?: boolean
showOwnerColumn: boolean
}
interface DatedDashboard extends Dashboard {
@ -57,29 +61,22 @@ class DashboardsTable extends PureComponent<Props & WithRouterProps, State> {
public render() {
const {sortKey, sortDirection} = this.state
const headerKeys: SortKey[] = ['name', 'owner', 'modified', 'default']
return (
<IndexList>
<IndexList.Header>
<IndexList.HeaderCell
columnName={headerKeys[0]}
sortKey={headerKeys[0]}
sort={sortKey === headerKeys[0] ? sortDirection : Sort.None}
width="62%"
columnName={this.headerKeys[0]}
sortKey={this.headerKeys[0]}
sort={sortKey === this.headerKeys[0] ? sortDirection : Sort.None}
width={this.nameColWidth}
onClick={this.handleClickColumn}
/>
{this.ownerColumnHeader}
<IndexList.HeaderCell
columnName={headerKeys[1]}
sortKey={headerKeys[1]}
sort={sortKey === headerKeys[1] ? sortDirection : Sort.None}
width="17%"
onClick={this.handleClickColumn}
/>
<IndexList.HeaderCell
columnName={headerKeys[2]}
sortKey={headerKeys[2]}
sort={sortKey === headerKeys[2] ? sortDirection : Sort.None}
columnName={this.headerKeys[2]}
sortKey={this.headerKeys[2]}
sort={sortKey === this.headerKeys[2] ? sortDirection : Sort.None}
width="11%"
onClick={this.handleClickColumn}
/>
@ -96,6 +93,37 @@ class DashboardsTable extends PureComponent<Props & WithRouterProps, State> {
)
}
private get headerKeys(): SortKey[] {
return ['name', 'owner', 'modified', 'default']
}
private get ownerColumnHeader(): JSX.Element {
const {showOwnerColumn} = this.props
const {sortKey, sortDirection} = this.state
if (showOwnerColumn) {
return (
<IndexList.HeaderCell
columnName={this.headerKeys[1]}
sortKey={this.headerKeys[1]}
sort={sortKey === this.headerKeys[1] ? sortDirection : Sort.None}
width={`${OWNER_COL_WIDTH}%`}
onClick={this.handleClickColumn}
/>
)
}
}
private get nameColWidth(): string {
const {showOwnerColumn} = this.props
if (showOwnerColumn) {
return `${NAME_COL_WIDTH}%`
}
return `${NAME_COL_WIDTH + OWNER_COL_WIDTH}%`
}
private handleClickColumn = (nextSort: Sort, sortKey: SortKey) => {
this.setState({sortKey, sortDirection: nextSort})
}
@ -109,7 +137,7 @@ class DashboardsTable extends PureComponent<Props & WithRouterProps, State> {
onUpdateDashboard,
onEditLabels,
orgs,
showInlineEdit,
showOwnerColumn,
} = this.props
const {sortKey, sortDirection} = this.state
@ -130,7 +158,7 @@ class DashboardsTable extends PureComponent<Props & WithRouterProps, State> {
onUpdateDashboard={onUpdateDashboard}
onEditLabels={onEditLabels}
orgs={orgs}
showInlineEdit={showInlineEdit}
showOwnerColumn={showOwnerColumn}
/>
)}
</SortingHat>

View File

@ -18,6 +18,7 @@ const setup = (override = {}) => {
onExportDashboard: jest.fn(),
onUpdateDashboard: jest.fn(),
onEditLabels: jest.fn(),
showOwnerColumn: true,
...override,
}

View File

@ -1,7 +1,6 @@
// Libraries
import React, {PureComponent} from 'react'
import {Link} from 'react-router'
import classnames from 'classnames'
// Components
import {
@ -37,7 +36,7 @@ interface Props {
onExportDashboard: (dashboard: Dashboard) => void
onUpdateDashboard: (dashboard: Dashboard) => void
onEditLabels: (dashboard: Dashboard) => void
showInlineEdit?: boolean
showOwnerColumn: boolean
}
export default class DashboardsIndexTableRow extends PureComponent<Props> {
@ -67,7 +66,7 @@ export default class DashboardsIndexTableRow extends PureComponent<Props> {
/>
</ComponentSpacer>
</IndexList.Cell>
<IndexList.Cell>{this.ownerName}</IndexList.Cell>
{this.ownerCell}
{this.lastModifiedCell}
<IndexList.Cell alignment={Alignment.Right} revealOnHover={true}>
<ComponentSpacer align={Alignment.Left} stackChildren={Stack.Columns}>
@ -91,21 +90,24 @@ export default class DashboardsIndexTableRow extends PureComponent<Props> {
)
}
private get resourceNames(): JSX.Element {
const {showInlineEdit, dashboard} = this.props
if (showInlineEdit) {
return (
<EditableName
onUpdate={this.handleUpdateDashboard}
name={dashboard.name}
hrefValue={`/dashboards/${dashboard.id}`}
/>
)
private get ownerCell(): JSX.Element {
const {showOwnerColumn} = this.props
if (showOwnerColumn) {
return <IndexList.Cell>{this.ownerName}</IndexList.Cell>
}
}
private get resourceNames(): JSX.Element {
const {dashboard} = this.props
return (
<Link className={this.nameClassName} to={`/dashboards/${dashboard.id}`}>
{this.name}
</Link>
<EditableName
onUpdate={this.handleUpdateDashboard}
name={dashboard.name}
hrefValue={`/dashboards/${dashboard.id}`}
noNameString={DEFAULT_DASHBOARD_NAME}
/>
)
}
@ -120,7 +122,6 @@ export default class DashboardsIndexTableRow extends PureComponent<Props> {
return (
<Label.Container
limitChildCount={4}
className="index-list--labels"
onEdit={this.handleEditLabels}
resourceName="this Dashboard"
/>
@ -167,12 +168,6 @@ export default class DashboardsIndexTableRow extends PureComponent<Props> {
onEditLabels(dashboard)
}
private get name(): string {
const {dashboard} = this.props
return dashboard.name || DEFAULT_DASHBOARD_NAME
}
private get ownerName(): JSX.Element {
const {dashboard, orgs} = this.props
const ownerOrg = orgs.find(o => o.id === dashboard.orgID)
@ -184,17 +179,6 @@ export default class DashboardsIndexTableRow extends PureComponent<Props> {
)
}
private get nameClassName(): string {
const {dashboard} = this.props
const dashboardIsUntitled =
dashboard.name === '' || dashboard.name === DEFAULT_DASHBOARD_NAME
return classnames('index-list--resource-name', {
'untitled-name': dashboardIsUntitled,
})
}
private handleUpdateDescription = (description: string): void => {
const {onUpdateDashboard} = this.props
const dashboard = {...this.props.dashboard, description}

View File

@ -15,7 +15,7 @@ interface Props {
onUpdateDashboard: (dashboard: Dashboard) => void
onEditLabels: (dashboard: Dashboard) => void
orgs: Organization[]
showInlineEdit?: boolean
showOwnerColumn: boolean
}
export default class DashboardsIndexTableRows extends PureComponent<Props> {
@ -28,7 +28,7 @@ export default class DashboardsIndexTableRows extends PureComponent<Props> {
onUpdateDashboard,
onEditLabels,
orgs,
showInlineEdit,
showOwnerColumn,
} = this.props
return dashboards.map(d => (
@ -41,7 +41,7 @@ export default class DashboardsIndexTableRows extends PureComponent<Props> {
onUpdateDashboard={onUpdateDashboard}
onEditLabels={onEditLabels}
orgs={orgs}
showInlineEdit={showInlineEdit}
showOwnerColumn={showOwnerColumn}
/>
))
}

View File

@ -89,6 +89,10 @@ type NewDefaultDashboard = Pick<
>
export const DEFAULT_CELL_NAME = 'Name this Cell'
export const DEFAULT_DASHBOARD_NAME = 'Name this Dashboard'
export const DEFAULT_BUCKET_NAME = 'Name this Bucket'
export const DEFAULT_COLLECTOR_NAME = 'Name this Collector'
export const DEFAULT_TASK_NAME = 'Name this Task'
export const DEFAULT_SCRAPER_NAME = 'Name this Scraper'
export const NEW_DASHBOARD: NewDefaultDashboard = {
name: DEFAULT_DASHBOARD_NAME,
cells: [NEW_DEFAULT_DASHBOARD_CELL],

View File

@ -12,6 +12,9 @@ import {
ComponentColor,
} from 'src/clockface'
// Constants
import {DEFAULT_BUCKET_NAME} from 'src/dashboards/constants'
// Types
import {Bucket} from '@influxdata/influx'
import {DataLoaderType} from 'src/types/v2/dataLoaders'
@ -40,6 +43,7 @@ export default class BucketRow extends PureComponent<Props> {
onUpdate={this.handleUpdateBucketName}
name={bucket.name}
onEditName={this.handleEditBucket}
noNameString={DEFAULT_BUCKET_NAME}
/>
</IndexList.Cell>
<IndexList.Cell>{bucket.ruleString}</IndexList.Cell>

View File

@ -14,6 +14,9 @@ import {
import {Telegraf} from '@influxdata/influx'
import EditableName from 'src/shared/components/EditableName'
// Constants
import {DEFAULT_COLLECTOR_NAME} from 'src/dashboards/constants'
interface Props {
collector: Telegraf
bucket: string
@ -33,6 +36,7 @@ export default class CollectorRow extends PureComponent<Props> {
<EditableName
onUpdate={this.handleUpdateConfig}
name={collector.name}
noNameString={DEFAULT_COLLECTOR_NAME}
/>
</IndexList.Cell>
<IndexList.Cell>{bucket}</IndexList.Cell>

View File

@ -6,13 +6,11 @@ import _ from 'lodash'
import {ComponentSize, EmptyState, IconFont, Input} from 'src/clockface'
import MemberList from 'src/organizations/components/MemberList'
import FilterList from 'src/shared/components/Filter'
import TabbedPageHeader from 'src/shared/components/tabbed_page/TabbedPageHeader'
// Types
import {ResourceOwner} from '@influxdata/influx'
// Constants
import TabbedPageHeader from 'src/shared/components/tabbed_page/TabbedPageHeader'
interface Props {
members: ResourceOwner[]
orgName: string

View File

@ -6,8 +6,7 @@ import {downloadTextFile} from 'src/shared/utils/download'
import _ from 'lodash'
// Components
import DashboardsContents from 'src/dashboards/components/dashboard_index/Contents'
import {Page} from 'src/pageLayout'
import DashboardsIndexContents from 'src/dashboards/components/dashboard_index/DashboardsIndexContents'
import {
OverlayTechnology,
Button,
@ -17,6 +16,7 @@ import {
} from 'src/clockface'
import ImportDashboardOverlay from 'src/dashboards/components/ImportDashboardOverlay'
import EditLabelsOverlay from 'src/shared/components/EditLabelsOverlay'
import TabbedPageHeader from 'src/shared/components/tabbed_page/TabbedPageHeader'
// Utils
import {getDeep} from 'src/utils/wrappers'
@ -116,46 +116,38 @@ class OrgDashboardIndex extends PureComponent<Props, State> {
return (
<>
<Page titleTag="Dashboards">
<Page.Header fullWidth={false}>
<Page.Header.Left>
<Input
icon={IconFont.Search}
placeholder="Filter tasks..."
widthPixels={290}
value={searchTerm}
onChange={this.handleFilterChange}
onBlur={this.handleFilterBlur}
/>
</Page.Header.Left>
<Page.Header.Right>
<Button
color={ComponentColor.Primary}
onClick={this.handleCreateDashboard}
icon={IconFont.Plus}
text="Create Dashboard"
titleText="Create a new dashboard"
/>
</Page.Header.Right>
</Page.Header>
<Page.Contents fullWidth={false} scrollable={true}>
<DashboardsContents
dashboards={dashboards}
orgs={orgs}
onSetDefaultDashboard={this.handleSetDefaultDashboard}
defaultDashboardLink={links.defaultDashboard}
onDeleteDashboard={this.handleDeleteDashboard}
onCreateDashboard={this.handleCreateDashboard}
onCloneDashboard={this.handleCloneDashboard}
onExportDashboard={this.handleExportDashboard}
onUpdateDashboard={handleUpdateDashboard}
onEditLabels={this.handleStartEditingLabels}
notify={notify}
searchTerm={searchTerm}
showInlineEdit={true}
/>
</Page.Contents>
</Page>
<TabbedPageHeader>
<Input
icon={IconFont.Search}
placeholder="Filter tasks..."
widthPixels={290}
value={searchTerm}
onChange={this.handleFilterChange}
onBlur={this.handleFilterBlur}
/>
<Button
color={ComponentColor.Primary}
onClick={this.handleCreateDashboard}
icon={IconFont.Plus}
text="Create Dashboard"
titleText="Create a new dashboard"
/>
</TabbedPageHeader>
<DashboardsIndexContents
dashboards={dashboards}
orgs={orgs}
onSetDefaultDashboard={this.handleSetDefaultDashboard}
defaultDashboardLink={links.defaultDashboard}
onDeleteDashboard={this.handleDeleteDashboard}
onCreateDashboard={this.handleCreateDashboard}
onCloneDashboard={this.handleCloneDashboard}
onExportDashboard={this.handleExportDashboard}
onUpdateDashboard={handleUpdateDashboard}
onEditLabels={this.handleStartEditingLabels}
notify={notify}
searchTerm={searchTerm}
showOwnerColumn={false}
/>
{this.renderImportOverlay}
{this.renderLabelEditorOverlay}
</>

View File

@ -11,6 +11,9 @@ import {
import {ScraperTargetResponse} from '@influxdata/influx'
import EditableName from 'src/shared/components/EditableName'
// Constants
import {DEFAULT_SCRAPER_NAME} from 'src/dashboards/constants'
interface Props {
scraper: ScraperTargetResponse
onDeleteScraper: (scraper) => void
@ -27,6 +30,7 @@ export default class ScraperRow extends PureComponent<Props> {
<EditableName
onUpdate={this.handleUpdateScraper}
name={scraper.url}
noNameString={DEFAULT_SCRAPER_NAME}
/>
</IndexList.Cell>
<IndexList.Cell>{scraper.bucket}</IndexList.Cell>

View File

@ -5,82 +5,78 @@
@import 'src/style/modules';
$rename-dash-title-padding: 5px;
$resource-name-font-size: 17px;
$resource-name-font-wight: 600;
$rename-dash-title-padding: 6px;
.editable-name {
height: $form-xs-height;
width: 100%;
margin-top: -3px;
}
.editable-name--preview,
.editable-name > a,
.input.editable-name--input > input {
font-size: $form-xs-font;
font-weight: 400;
font-size: $resource-name-font-size;
font-weight: $resource-name-font-wight;
font-family: $ix-text-font;
padding: 0 $rename-dash-title-padding;
}
.editable-name--preview,
.editable-name--input {
position: relative;
width: 100%;
.editable-name > a {
white-space: nowrap;
line-height: $resource-name-font-size;
padding-left: ($rename-dash-title-padding + $ix-border);
padding-right: 0;
}
.editable-name--preview {
display: inline-flex;
justify-content: flex-start;
align-items: center;
border-radius: $radius;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@include no-user-select();
color: $g13-mist;
transition: color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
border: $ix-border solid transparent;
.editable-name {
height: $form-xs-height;
line-height: $form-xs-height - ($ix-border * 2);
.icon {
position: relative;
display: inline-block;
margin-left: $ix-marg-b;
opacity: 0;
transition: opacity 0.25s ease;
color: $g11-sidewalk;
}
&:hover .icon {
opacity: 1;
}
&.untitled {
color: $g9-mountain;
font-style: italic;
}
position: relative;
display: inline-block;
}
.editable-name--toggle {
font-size: $resource-name-font-size * 0.75;
transform: translateY(-10%);
padding: $ix-marg-a;
display: inline-block;
margin-left: $ix-marg-b;
transition: color 0.25s ease, opacity 0.25s ease;
opacity: 1;
color: $g11-sidewalk;
&:hover {
cursor: text;
color: $g20-white;
// background-color: $g3-castle;
// border-color: $g3-castle;
cursor: pointer;
color: $g15-platinum;
}
}
.input.editable-name--input {
position: absolute;
top: -1px;
left: 0;
width: 100%;
}
/* Ensure placeholder text matches font weight of title */
.input.editable-name--input > input {
&::-webkit-input-placeholder {
font-weight: $page-title-weight !important;
font-weight: $resource-name-font-wight !important;
}
&::-moz-placeholder {
font-weight: $page-title-weight !important;
font-weight: $resource-name-font-wight !important;
}
&:-ms-input-placeholder {
font-weight: $page-title-weight !important;
font-weight: $resource-name-font-wight !important;
}
&:-moz-placeholder {
font-weight: $page-title-weight !important;
font-weight: $resource-name-font-wight !important;
}
}
/* When used inside an index list, hide edit button until row hover */
.index-list--row .editable-name--toggle {
opacity: 0;
}
.index-list--row:hover .editable-name--toggle {
opacity: 1;
}

View File

@ -12,14 +12,20 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
// Styles
import 'src/shared/components/EditableName.scss'
interface Props {
interface PassedProps {
onUpdate: (name: string) => void
name: string
onEditName: (e?: MouseEvent<HTMLAnchorElement>) => void
hrefValue?: string
onEditName?: (e?: MouseEvent<HTMLAnchorElement>) => void
placeholder?: string
noNameString: string
}
interface DefaultProps {
hrefValue?: string
}
type Props = PassedProps & DefaultProps
interface State {
isEditing: boolean
workingName: string
@ -27,9 +33,10 @@ interface State {
@ErrorHandling
class EditableName extends Component<Props, State> {
public static defaultProps: Partial<Props> = {
public static defaultProps: DefaultProps = {
hrefValue: '#',
}
constructor(props: Props) {
super(props)
@ -40,54 +47,46 @@ class EditableName extends Component<Props, State> {
}
public render() {
const {name, onEditName, hrefValue} = this.props
const {isEditing} = this.state
if (isEditing) {
return (
<div className="editable-name">
<ClickOutside onClickOutside={this.handleStopEditing}>
{this.input}
</ClickOutside>
</div>
)
}
const {name, onEditName, hrefValue, noNameString} = this.props
return (
<>
<div className={this.className}>
<a href={hrefValue} onClick={onEditName}>
<span>{name || 'No name'}</span>
<span>{name || noNameString}</span>
</a>
<div className="editable-name">
<div
className={this.previewClassName}
onClick={this.handleStartEditing}
>
<span className="icon pencil" />
</div>
<div
className="editable-name--toggle"
onClick={this.handleStartEditing}
>
<span className="icon pencil" />
</div>
</>
{this.input}
</div>
)
}
private get input(): JSX.Element {
const {placeholder} = this.props
const {workingName} = this.state
const {workingName, isEditing} = this.state
return (
<Input
size={ComponentSize.ExtraSmall}
maxLength={90}
autoFocus={true}
spellCheck={false}
placeholder={placeholder}
onFocus={this.handleInputFocus}
onChange={this.handleInputChange}
onKeyDown={this.handleKeyDown}
customClass="editable-name--input"
value={workingName}
/>
)
if (isEditing) {
return (
<ClickOutside onClickOutside={this.handleStopEditing}>
<Input
size={ComponentSize.ExtraSmall}
maxLength={90}
autoFocus={true}
spellCheck={false}
placeholder={placeholder}
onFocus={this.handleInputFocus}
onChange={this.handleInputChange}
onKeyDown={this.handleKeyDown}
customClass="editable-name--input"
value={workingName}
/>
</ClickOutside>
)
}
}
private handleStartEditing = (): void => {
@ -127,11 +126,11 @@ class EditableName extends Component<Props, State> {
e.currentTarget.select()
}
private get previewClassName(): string {
const {name} = this.props
private get className(): string {
const {name, noNameString} = this.props
return classnames('editable-name--preview', {
untitled: name === '',
return classnames('editable-name', {
'untitled-name': name === noNameString,
})
}
}

View File

@ -20,6 +20,9 @@ import {
import {downloadTextFile} from 'src/shared/utils/download'
import {Task as TaskAPI, Organization} from '@influxdata/influx'
// Constants
import {DEFAULT_TASK_NAME} from 'src/dashboards/constants'
interface Task extends TaskAPI {
organization: Organization
}
@ -102,6 +105,7 @@ export class TaskRow extends PureComponent<Props & WithRouterProps> {
onUpdate={this.handleUpdateTask}
name={task.name}
onEditName={this.handleClick}
noNameString={DEFAULT_TASK_NAME}
/>
)
}