Merge pull request #12703 from influxdata/refactor/add-note-dashboard
Refactor/add note dashboardpull/12712/head
commit
a6abcea690
|
@ -9,6 +9,7 @@
|
|||
### Bug Fixes
|
||||
|
||||
1. [12684](https://github.com/influxdata/influxdb/pull/12684): Fix mismatch in bucket row and header
|
||||
1. [12703](https://github.com/influxdata/influxdb/pull/12703): Allows user to edit note on cell
|
||||
|
||||
### UI Improvements
|
||||
|
||||
|
|
|
@ -7,42 +7,21 @@ import {updateView} from 'src/dashboards/actions/views'
|
|||
|
||||
// Utils
|
||||
import {createView} from 'src/shared/utils/view'
|
||||
import {getView} from 'src/dashboards/selectors'
|
||||
|
||||
// Types
|
||||
import {GetState} from 'src/types/v2'
|
||||
import {NoteEditorMode, MarkdownView, ViewType} from 'src/types/v2/dashboards'
|
||||
import {NoteEditorState} from 'src/dashboards/reducers/notes'
|
||||
import {Dispatch} from 'redux-thunk'
|
||||
|
||||
export type Action =
|
||||
| OpenNoteEditorAction
|
||||
| CloseNoteEditorAction
|
||||
| SetIsPreviewingAction
|
||||
| ToggleShowNoteWhenEmptyAction
|
||||
| SetNoteAction
|
||||
|
||||
interface OpenNoteEditorAction {
|
||||
type: 'OPEN_NOTE_EDITOR'
|
||||
payload: {initialState: Partial<NoteEditorState>}
|
||||
}
|
||||
|
||||
export const openNoteEditor = (
|
||||
initialState: Partial<NoteEditorState>
|
||||
): OpenNoteEditorAction => ({
|
||||
type: 'OPEN_NOTE_EDITOR',
|
||||
payload: {initialState},
|
||||
})
|
||||
|
||||
export const addNote = (): OpenNoteEditorAction => ({
|
||||
type: 'OPEN_NOTE_EDITOR',
|
||||
payload: {
|
||||
initialState: {
|
||||
mode: NoteEditorMode.Adding,
|
||||
viewID: null,
|
||||
toggleVisible: false,
|
||||
note: '',
|
||||
},
|
||||
},
|
||||
})
|
||||
| SetNoteStateAction
|
||||
| ResetNoteStateAction
|
||||
|
||||
interface CloseNoteEditorAction {
|
||||
type: 'CLOSE_NOTE_EDITOR'
|
||||
|
@ -83,7 +62,7 @@ export const setNote = (note: string): SetNoteAction => ({
|
|||
})
|
||||
|
||||
export const createNoteCell = (dashboardID: string) => async (
|
||||
dispatch,
|
||||
dispatch: Dispatch<Action>,
|
||||
getState: GetState
|
||||
) => {
|
||||
const dashboard = getState().dashboards.find(d => d.id === dashboardID)
|
||||
|
@ -100,13 +79,68 @@ export const createNoteCell = (dashboardID: string) => async (
|
|||
return dispatch(createCellWithView(dashboard, view))
|
||||
}
|
||||
|
||||
export const updateViewNote = () => async (dispatch, getState: GetState) => {
|
||||
export interface ResetNoteStateAction {
|
||||
type: 'RESET_NOTE_STATE'
|
||||
}
|
||||
|
||||
export const resetNoteState = (): ResetNoteStateAction => ({
|
||||
type: 'RESET_NOTE_STATE',
|
||||
})
|
||||
|
||||
export interface SetNoteStateAction {
|
||||
type: 'SET_NOTE_STATE'
|
||||
payload: Partial<NoteEditorState>
|
||||
}
|
||||
|
||||
export const setNoteState = (
|
||||
noteState: Partial<NoteEditorState>
|
||||
): SetNoteStateAction => ({
|
||||
type: 'SET_NOTE_STATE',
|
||||
payload: noteState,
|
||||
})
|
||||
|
||||
export const loadNote = (id: string) => async (
|
||||
dispatch: Dispatch<Action>,
|
||||
getState: GetState
|
||||
) => {
|
||||
const {
|
||||
views: {views},
|
||||
} = getState()
|
||||
const currentViewState = views[id]
|
||||
|
||||
if (!currentViewState) {
|
||||
return
|
||||
}
|
||||
|
||||
const view = currentViewState.view
|
||||
|
||||
const note: string = get(view, 'properties.note', '')
|
||||
const showNoteWhenEmpty: boolean = get(
|
||||
view,
|
||||
'properties.showNoteWhenEmpty',
|
||||
false
|
||||
)
|
||||
|
||||
const initialState = {
|
||||
viewID: view.id,
|
||||
note,
|
||||
showNoteWhenEmpty,
|
||||
mode: NoteEditorMode.Editing,
|
||||
}
|
||||
|
||||
dispatch(setNoteState(initialState))
|
||||
}
|
||||
|
||||
export const updateViewNote = (id: string) => async (
|
||||
dispatch: Dispatch<Action>,
|
||||
getState: GetState
|
||||
) => {
|
||||
const state = getState()
|
||||
const {note, showNoteWhenEmpty, viewID} = state.noteEditor
|
||||
const view: any = get(state, `views.${viewID}.view`)
|
||||
const {note, showNoteWhenEmpty} = state.noteEditor
|
||||
const view: any = getView(state, id)
|
||||
|
||||
if (!view) {
|
||||
throw new Error(`could not find view with id "${viewID}"`)
|
||||
throw new Error(`could not find view with id "${id}"`)
|
||||
}
|
||||
|
||||
if (isUndefined(view.properties.note)) {
|
||||
|
|
|
@ -24,6 +24,7 @@ interface Props {
|
|||
setScrollTop: (e: MouseEvent<HTMLElement>) => void
|
||||
onEditView: (cellID: string) => void
|
||||
onAddCell: () => void
|
||||
onEditNote: (id: string) => void
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
|
@ -42,6 +43,7 @@ class DashboardComponent extends PureComponent<Props> {
|
|||
inPresentationMode,
|
||||
setScrollTop,
|
||||
onAddCell,
|
||||
onEditNote,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
|
@ -63,6 +65,7 @@ class DashboardComponent extends PureComponent<Props> {
|
|||
onDeleteCell={onDeleteCell}
|
||||
onPositionChange={onPositionChange}
|
||||
onEditView={onEditView}
|
||||
onEditNote={onEditNote}
|
||||
/>
|
||||
) : (
|
||||
<DashboardEmpty onAddCell={onAddCell} />
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Libraries
|
||||
import React, {Component} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
// Components
|
||||
import {Page} from 'src/pageLayout'
|
||||
|
@ -21,15 +20,16 @@ import {
|
|||
DASHBOARD_NAME_MAX_LENGTH,
|
||||
} from 'src/dashboards/constants/index'
|
||||
|
||||
// Actions
|
||||
import {addNote} from 'src/dashboards/actions/notes'
|
||||
|
||||
// Types
|
||||
import * as AppActions from 'src/types/actions/app'
|
||||
import * as QueriesModels from 'src/types/queries'
|
||||
import {Dashboard} from '@influxdata/influx'
|
||||
|
||||
interface OwnProps {
|
||||
interface DefaultProps {
|
||||
zoomedTimeRange: QueriesModels.TimeRange
|
||||
}
|
||||
|
||||
interface Props extends DefaultProps {
|
||||
activeDashboard: string
|
||||
dashboard: Dashboard
|
||||
timeRange: QueriesModels.TimeRange
|
||||
|
@ -40,21 +40,15 @@ interface OwnProps {
|
|||
handleClickPresentationButton: AppActions.DelayEnablePresentationModeDispatcher
|
||||
onAddCell: () => void
|
||||
showTemplateControlBar: boolean
|
||||
zoomedTimeRange: QueriesModels.TimeRange
|
||||
onRenameDashboard: (name: string) => Promise<void>
|
||||
toggleVariablesControlBar: () => void
|
||||
isShowingVariablesControlBar: boolean
|
||||
isHidden: boolean
|
||||
onAddNote: () => void
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
onAddNote: typeof addNote
|
||||
}
|
||||
|
||||
type Props = OwnProps & DispatchProps
|
||||
|
||||
class DashboardHeader extends Component<Props> {
|
||||
public static defaultProps: Partial<Props> = {
|
||||
export default class DashboardHeader extends Component<Props> {
|
||||
public static defaultProps: DefaultProps = {
|
||||
zoomedTimeRange: {
|
||||
upper: null,
|
||||
lower: null,
|
||||
|
@ -70,21 +64,36 @@ class DashboardHeader extends Component<Props> {
|
|||
timeRange: {upper, lower},
|
||||
zoomedTimeRange: {upper: zoomedUpper, lower: zoomedLower},
|
||||
isHidden,
|
||||
onAddNote,
|
||||
toggleVariablesControlBar,
|
||||
isShowingVariablesControlBar,
|
||||
onAddCell,
|
||||
onRenameDashboard,
|
||||
activeDashboard,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<Page.Header fullWidth={true} inPresentationMode={isHidden}>
|
||||
<Page.Header.Left>{this.dashboardTitle}</Page.Header.Left>
|
||||
<Page.Header.Left>
|
||||
<RenamablePageTitle
|
||||
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
||||
onRename={onRenameDashboard}
|
||||
name={activeDashboard}
|
||||
placeholder={DEFAULT_DASHBOARD_NAME}
|
||||
/>
|
||||
</Page.Header.Left>
|
||||
<Page.Header.Right>
|
||||
<GraphTips />
|
||||
{this.addCellButton}
|
||||
<Button
|
||||
icon={IconFont.AddCell}
|
||||
color={ComponentColor.Primary}
|
||||
onClick={onAddCell}
|
||||
text="Add Cell"
|
||||
titleText="Add cell to dashboard"
|
||||
/>
|
||||
<Button
|
||||
icon={IconFont.TextBlock}
|
||||
text="Add Note"
|
||||
onClick={onAddNote}
|
||||
onClick={this.handleAddNote}
|
||||
/>
|
||||
<AutoRefreshDropdown
|
||||
onChoose={handleChooseAutoRefresh}
|
||||
|
@ -118,49 +127,11 @@ class DashboardHeader extends Component<Props> {
|
|||
)
|
||||
}
|
||||
|
||||
private handleAddNote = () => {
|
||||
this.props.onAddNote()
|
||||
}
|
||||
|
||||
private handleClickPresentationButton = (): void => {
|
||||
this.props.handleClickPresentationButton()
|
||||
}
|
||||
|
||||
private get addCellButton(): JSX.Element {
|
||||
const {dashboard, onAddCell} = this.props
|
||||
|
||||
if (dashboard) {
|
||||
return (
|
||||
<Button
|
||||
icon={IconFont.AddCell}
|
||||
color={ComponentColor.Primary}
|
||||
onClick={onAddCell}
|
||||
text="Add Cell"
|
||||
titleText="Add cell to dashboard"
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private get dashboardTitle(): JSX.Element {
|
||||
const {dashboard, activeDashboard, onRenameDashboard} = this.props
|
||||
|
||||
if (dashboard) {
|
||||
return (
|
||||
<RenamablePageTitle
|
||||
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
||||
onRename={onRenameDashboard}
|
||||
name={activeDashboard}
|
||||
placeholder={DEFAULT_DASHBOARD_NAME}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return <Page.Title title={activeDashboard} />
|
||||
}
|
||||
}
|
||||
|
||||
const mdtp = {
|
||||
onAddNote: addNote,
|
||||
}
|
||||
|
||||
export default connect<{}, DispatchProps, OwnProps>(
|
||||
null,
|
||||
mdtp
|
||||
)(DashboardHeader)
|
||||
|
|
|
@ -11,7 +11,6 @@ import DashboardHeader from 'src/dashboards/components/DashboardHeader'
|
|||
import DashboardComponent from 'src/dashboards/components/Dashboard'
|
||||
import ManualRefresh from 'src/shared/components/ManualRefresh'
|
||||
import {HoverTimeProvider} from 'src/dashboards/utils/hoverTime'
|
||||
import NoteEditorContainer from 'src/dashboards/components/NoteEditorContainer'
|
||||
import VariablesControlBar from 'src/dashboards/components/variablesControlBar/VariablesControlBar'
|
||||
|
||||
// Actions
|
||||
|
@ -164,6 +163,7 @@ class DashboardPage extends Component<Props, State> {
|
|||
autoRefresh={autoRefresh}
|
||||
isHidden={inPresentationMode}
|
||||
onAddCell={this.handleAddCell}
|
||||
onAddNote={this.showNoteOverlay}
|
||||
onManualRefresh={onManualRefresh}
|
||||
zoomedTimeRange={zoomedTimeRange}
|
||||
onRenameDashboard={this.handleRenameDashboard}
|
||||
|
@ -193,11 +193,11 @@ class DashboardPage extends Component<Props, State> {
|
|||
onDeleteCell={this.handleDeleteDashboardCell}
|
||||
onEditView={this.handleEditView}
|
||||
onAddCell={this.handleAddCell}
|
||||
onEditNote={this.showNoteOverlay}
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
</HoverTimeProvider>
|
||||
<NoteEditorContainer />
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
@ -240,6 +240,14 @@ class DashboardPage extends Component<Props, State> {
|
|||
this.showVEO()
|
||||
}
|
||||
|
||||
private showNoteOverlay = async (id?: string): Promise<void> => {
|
||||
if (id) {
|
||||
this.props.router.push(`${this.props.location.pathname}/notes/${id}/edit`)
|
||||
} else {
|
||||
this.props.router.push(`${this.props.location.pathname}/notes/new`)
|
||||
}
|
||||
}
|
||||
|
||||
private handleEditView = (cellID: string): void => {
|
||||
this.showVEO(cellID)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import {AppState} from 'src/types/v2'
|
|||
|
||||
interface StateProps {
|
||||
note: string
|
||||
toggleVisible: boolean
|
||||
showNoteWhenEmpty: boolean
|
||||
}
|
||||
|
||||
|
@ -69,36 +68,25 @@ class NoteEditor extends PureComponent<Props> {
|
|||
}
|
||||
|
||||
private get visibilityToggle(): JSX.Element {
|
||||
const {
|
||||
toggleVisible,
|
||||
showNoteWhenEmpty,
|
||||
onToggleShowNoteWhenEmpty,
|
||||
} = this.props
|
||||
const {showNoteWhenEmpty, onToggleShowNoteWhenEmpty} = this.props
|
||||
|
||||
if (toggleVisible) {
|
||||
return (
|
||||
<ComponentSpacer stackChildren={Stack.Columns} align={Alignment.Right}>
|
||||
<SlideToggle.Label text="Show note when query returns no data" />
|
||||
<SlideToggle
|
||||
active={showNoteWhenEmpty}
|
||||
size={ComponentSize.ExtraSmall}
|
||||
onChange={onToggleShowNoteWhenEmpty}
|
||||
/>
|
||||
</ComponentSpacer>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<ComponentSpacer stackChildren={Stack.Columns} align={Alignment.Right}>
|
||||
<SlideToggle.Label text="Show note when query returns no data" />
|
||||
<SlideToggle
|
||||
active={showNoteWhenEmpty}
|
||||
size={ComponentSize.ExtraSmall}
|
||||
onChange={onToggleShowNoteWhenEmpty}
|
||||
/>
|
||||
</ComponentSpacer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mstp = (state: AppState) => {
|
||||
const {
|
||||
note,
|
||||
isPreviewing,
|
||||
toggleVisible,
|
||||
showNoteWhenEmpty,
|
||||
} = state.noteEditor
|
||||
const {note, isPreviewing, showNoteWhenEmpty} = state.noteEditor
|
||||
|
||||
return {note, isPreviewing, toggleVisible, showNoteWhenEmpty}
|
||||
return {note, isPreviewing, showNoteWhenEmpty}
|
||||
}
|
||||
|
||||
const mdtp = {
|
||||
|
|
|
@ -10,9 +10,10 @@ import {Overlay} from 'src/clockface'
|
|||
|
||||
// Actions
|
||||
import {
|
||||
closeNoteEditor,
|
||||
createNoteCell,
|
||||
updateViewNote,
|
||||
loadNote,
|
||||
resetNoteState,
|
||||
} from 'src/dashboards/actions/notes'
|
||||
import {notify} from 'src/shared/actions/notifications'
|
||||
|
||||
|
@ -26,41 +27,43 @@ import {NoteEditorMode} from 'src/types/v2/dashboards'
|
|||
|
||||
interface StateProps {
|
||||
mode: NoteEditorMode
|
||||
overlayVisible: boolean
|
||||
viewID: string
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
onHide: typeof closeNoteEditor
|
||||
onCreateNoteCell: (dashboardID: string) => Promise<void>
|
||||
onUpdateViewNote: () => Promise<void>
|
||||
onCreateNoteCell: typeof createNoteCell
|
||||
onUpdateViewNote: typeof updateViewNote
|
||||
resetNote: typeof resetNoteState
|
||||
onNotify: typeof notify
|
||||
loadNote: typeof loadNote
|
||||
}
|
||||
|
||||
interface OwnProps {}
|
||||
interface RouterProps extends WithRouterProps {
|
||||
params: {
|
||||
dashboardID: string
|
||||
cellID?: string
|
||||
}
|
||||
}
|
||||
|
||||
type Props = StateProps & DispatchProps & OwnProps & WithRouterProps
|
||||
type Props = StateProps & DispatchProps & RouterProps
|
||||
|
||||
interface State {
|
||||
savingStatus: RemoteDataState
|
||||
}
|
||||
|
||||
class NoteEditorContainer extends PureComponent<Props, State> {
|
||||
class NoteEditorOverlay extends PureComponent<Props, State> {
|
||||
public state: State = {savingStatus: RemoteDataState.NotStarted}
|
||||
|
||||
public render() {
|
||||
const {onHide, overlayVisible} = this.props
|
||||
|
||||
return (
|
||||
<div className="note-editor-container">
|
||||
<Overlay visible={overlayVisible}>
|
||||
<Overlay visible={true}>
|
||||
<Overlay.Container maxWidth={900}>
|
||||
<Overlay.Heading title={this.overlayTitle} onDismiss={onHide} />
|
||||
<Overlay.Heading title={this.overlayTitle} onDismiss={this.close} />
|
||||
<Overlay.Body>
|
||||
<NoteEditor />
|
||||
</Overlay.Body>
|
||||
<Overlay.Footer>
|
||||
<Button text="Cancel" onClick={onHide} />
|
||||
<Button text="Cancel" onClick={this.close} />
|
||||
<Button
|
||||
text="Save"
|
||||
color={ComponentColor.Success}
|
||||
|
@ -74,6 +77,17 @@ class NoteEditorContainer extends PureComponent<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
params: {cellID},
|
||||
} = this.props
|
||||
if (cellID) {
|
||||
this.props.loadNote(cellID)
|
||||
} else {
|
||||
this.props.resetNote()
|
||||
}
|
||||
}
|
||||
|
||||
private get overlayTitle(): string {
|
||||
const {mode} = this.props
|
||||
|
||||
|
@ -100,47 +114,48 @@ class NoteEditorContainer extends PureComponent<Props, State> {
|
|||
|
||||
private handleSave = async () => {
|
||||
const {
|
||||
viewID,
|
||||
params: {cellID, dashboardID},
|
||||
onCreateNoteCell,
|
||||
onUpdateViewNote,
|
||||
onHide,
|
||||
onNotify,
|
||||
} = this.props
|
||||
|
||||
const dashboardID = this.props.params.dashboardID
|
||||
|
||||
this.setState({savingStatus: RemoteDataState.Loading})
|
||||
|
||||
try {
|
||||
if (viewID) {
|
||||
await onUpdateViewNote()
|
||||
if (cellID) {
|
||||
await onUpdateViewNote(cellID)
|
||||
} else {
|
||||
await onCreateNoteCell(dashboardID)
|
||||
}
|
||||
|
||||
this.setState({savingStatus: RemoteDataState.NotStarted}, onHide)
|
||||
this.close()
|
||||
} catch (error) {
|
||||
onNotify(savingNoteFailed(error.message))
|
||||
console.error(error)
|
||||
this.setState({savingStatus: RemoteDataState.Error})
|
||||
}
|
||||
}
|
||||
|
||||
private close = () => {
|
||||
this.props.router.goBack()
|
||||
}
|
||||
}
|
||||
|
||||
const mstp = (state: AppState) => {
|
||||
const {mode, overlayVisible, viewID} = state.noteEditor
|
||||
const mstp = (state: AppState): StateProps => {
|
||||
const {mode} = state.noteEditor
|
||||
|
||||
return {mode, overlayVisible, viewID}
|
||||
return {mode}
|
||||
}
|
||||
|
||||
const mdtp = {
|
||||
onHide: closeNoteEditor,
|
||||
onNotify: notify,
|
||||
onCreateNoteCell: createNoteCell as any,
|
||||
onUpdateViewNote: updateViewNote as any,
|
||||
onCreateNoteCell: createNoteCell,
|
||||
onUpdateViewNote: updateViewNote,
|
||||
resetNote: resetNoteState,
|
||||
loadNote,
|
||||
}
|
||||
|
||||
export default connect<StateProps, DispatchProps, OwnProps>(
|
||||
export default connect<StateProps, DispatchProps, {}>(
|
||||
mstp,
|
||||
mdtp
|
||||
)(withRouter<StateProps & DispatchProps & OwnProps>(NoteEditorContainer))
|
||||
)(withRouter<StateProps & DispatchProps>(NoteEditorOverlay))
|
|
@ -2,20 +2,14 @@ import {Action} from 'src/dashboards/actions/notes'
|
|||
import {NoteEditorMode} from 'src/types/v2/dashboards'
|
||||
|
||||
export interface NoteEditorState {
|
||||
overlayVisible: boolean
|
||||
mode: NoteEditorMode
|
||||
viewID: string
|
||||
toggleVisible: boolean
|
||||
note: string
|
||||
showNoteWhenEmpty: boolean
|
||||
isPreviewing: boolean
|
||||
}
|
||||
|
||||
const initialState = (): NoteEditorState => ({
|
||||
overlayVisible: false,
|
||||
mode: NoteEditorMode.Adding,
|
||||
viewID: null,
|
||||
toggleVisible: false,
|
||||
note: '',
|
||||
showNoteWhenEmpty: false,
|
||||
isPreviewing: false,
|
||||
|
@ -26,13 +20,15 @@ const noteEditorReducer = (
|
|||
action: Action
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case 'OPEN_NOTE_EDITOR': {
|
||||
const {initialState} = action.payload
|
||||
case 'RESET_NOTE_STATE': {
|
||||
return initialState()
|
||||
}
|
||||
case 'SET_NOTE_STATE': {
|
||||
const initialState = action.payload
|
||||
|
||||
return {
|
||||
...state,
|
||||
...initialState,
|
||||
overlayVisible: true,
|
||||
isPreviewing: false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import OrgTasksIndex from 'src/organizations/containers/OrgTasksIndex'
|
|||
import TaskExportOverlay from 'src/organizations/components/TaskExportOverlay'
|
||||
import TaskImportOverlay from 'src/organizations/components/TaskImportOverlay'
|
||||
import VEO from 'src/dashboards/components/VEO'
|
||||
import NoteEditorOverlay from 'src/dashboards/components/NoteEditorOverlay'
|
||||
|
||||
import OnboardingWizardPage from 'src/onboarding/containers/OnboardingWizardPage'
|
||||
|
||||
|
@ -182,6 +183,13 @@ class Root extends PureComponent {
|
|||
<Route path="new" component={VEO} />
|
||||
<Route path=":cellID/edit" component={VEO} />
|
||||
</Route>
|
||||
<Route path="notes">
|
||||
<Route path="new" component={NoteEditorOverlay} />
|
||||
<Route
|
||||
path=":cellID/edit"
|
||||
component={NoteEditorOverlay}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route
|
||||
path=":dashboardID/export"
|
||||
|
|
|
@ -31,6 +31,7 @@ interface OwnProps {
|
|||
onDeleteCell: (cell: Cell) => void
|
||||
onCloneCell: (cell: Cell) => void
|
||||
onEditCell: () => void
|
||||
onEditNote: (id: string) => void
|
||||
onZoom: (range: TimeRange) => void
|
||||
}
|
||||
|
||||
|
@ -39,7 +40,14 @@ type Props = StateProps & OwnProps
|
|||
@ErrorHandling
|
||||
class CellComponent extends Component<Props> {
|
||||
public render() {
|
||||
const {onEditCell, onDeleteCell, onCloneCell, cell, view} = this.props
|
||||
const {
|
||||
onEditCell,
|
||||
onEditNote,
|
||||
onDeleteCell,
|
||||
onCloneCell,
|
||||
cell,
|
||||
view,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -51,6 +59,7 @@ class CellComponent extends Component<Props> {
|
|||
onDeleteCell={onDeleteCell}
|
||||
onCloneCell={onCloneCell}
|
||||
onEditCell={onEditCell}
|
||||
onEditNote={onEditNote}
|
||||
onCSVDownload={this.handleCSVDownload}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -1,37 +1,27 @@
|
|||
// Libraries
|
||||
import React, {PureComponent} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import {get} from 'lodash'
|
||||
|
||||
// Components
|
||||
import {Context} from 'src/clockface'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
// Actions
|
||||
import {openNoteEditor} from 'src/dashboards/actions/notes'
|
||||
|
||||
// Types
|
||||
import {IconFont, ComponentColor} from '@influxdata/clockface'
|
||||
import {Cell, View, ViewType} from 'src/types/v2'
|
||||
import {NoteEditorMode} from 'src/types/v2/dashboards'
|
||||
|
||||
interface OwnProps {
|
||||
interface Props {
|
||||
cell: Cell
|
||||
view: View
|
||||
onDeleteCell: (cell: Cell) => void
|
||||
onCloneCell: (cell: Cell) => void
|
||||
onCSVDownload: () => void
|
||||
onEditCell: () => void
|
||||
onEditNote: (id: string) => void
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
onOpenNoteEditor: typeof openNoteEditor
|
||||
}
|
||||
|
||||
type Props = DispatchProps & OwnProps
|
||||
|
||||
@ErrorHandling
|
||||
class CellContext extends PureComponent<Props> {
|
||||
export default class CellContext extends PureComponent<Props> {
|
||||
public render() {
|
||||
const {cell, onDeleteCell, onCloneCell} = this.props
|
||||
|
||||
|
@ -77,32 +67,11 @@ class CellContext extends PureComponent<Props> {
|
|||
}
|
||||
|
||||
private handleEditNote = () => {
|
||||
const {onOpenNoteEditor, view} = this.props
|
||||
const {
|
||||
view: {id},
|
||||
onEditNote,
|
||||
} = this.props
|
||||
|
||||
const note: string = get(view, 'properties.note', '')
|
||||
const showNoteWhenEmpty: boolean = get(
|
||||
view,
|
||||
'properties.showNoteWhenEmpty',
|
||||
false
|
||||
)
|
||||
|
||||
const initialState = {
|
||||
viewID: view.id,
|
||||
toggleVisible: view.properties.type !== ViewType.Markdown,
|
||||
note,
|
||||
showNoteWhenEmpty,
|
||||
mode: note === '' ? NoteEditorMode.Adding : NoteEditorMode.Editing,
|
||||
}
|
||||
|
||||
onOpenNoteEditor(initialState)
|
||||
onEditNote(id)
|
||||
}
|
||||
}
|
||||
|
||||
const mdtp = {
|
||||
onOpenNoteEditor: openNoteEditor,
|
||||
}
|
||||
|
||||
export default connect<{}, DispatchProps, OwnProps>(
|
||||
null,
|
||||
mdtp
|
||||
)(CellContext)
|
||||
|
|
|
@ -39,6 +39,7 @@ interface Props {
|
|||
onDeleteCell?: (cell: Cell) => void
|
||||
onPositionChange?: (cells: Cell[]) => void
|
||||
onEditView: (cellID: string) => void
|
||||
onEditNote: (id: string) => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -64,6 +65,7 @@ class Cells extends Component<Props & WithRouterProps, State> {
|
|||
timeRange,
|
||||
autoRefresh,
|
||||
manualRefresh,
|
||||
onEditNote,
|
||||
} = this.props
|
||||
const {rowHeight} = this.state
|
||||
|
||||
|
@ -91,6 +93,7 @@ class Cells extends Component<Props & WithRouterProps, State> {
|
|||
onCloneCell={onCloneCell}
|
||||
onDeleteCell={onDeleteCell}
|
||||
onEditCell={this.handleEditCell(cell)}
|
||||
onEditNote={onEditNote}
|
||||
/>
|
||||
{this.cellBorder}
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue