Skip to content

Commit 79eb18c

Browse files
authored
feat: get all the version history for the user and have a hover state with a glimpse at the publish by and publish at (#3801)
1 parent 43f4e70 commit 79eb18c

File tree

7 files changed

+239
-36
lines changed

7 files changed

+239
-36
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"cy": "CYPRESS_dexUrl=https://$INGRESS_HOST:$PORT_HTTPS CYPRESS_baseUrl=http://localhost:9999 cypress open",
5353
"cy:dev": "source ../monitor-ci/.env && CYPRESS_dexUrl=CLOUD CYPRESS_baseUrl=https://$INGRESS_HOST:$PORT_HTTPS cypress open --config testFiles='{cloud,shared}/**/*.*'",
5454
"cy:dev-oss": "source ../monitor-ci/.env && CYPRESS_dexUrl=OSS CYPRESS_baseUrl=https://$INGRESS_HOST:$PORT_HTTPS cypress open --config testFiles='{oss,shared}/**/*.*'",
55-
"generate": "export SHA=6d62bf9d76c012558a3c7d8848461d408e87f9db && export REMOTE=https://raw.githubusercontent.com/influxdata/openapi/${SHA}/ && yarn generate-meta",
55+
"generate": "export SHA=2670263b84efd14387ffcaa01102db328cded3e4 && export REMOTE=https://raw.githubusercontent.com/influxdata/openapi/${SHA}/ && yarn generate-meta",
5656
"generate-local": "export REMOTE=../openapi/ && yarn generate-meta",
5757
"generate-meta": "if [ -z \"${CLOUD_URL}\" ]; then yarn generate-meta-oss; else yarn generate-meta-cloud; fi",
5858
"generate-meta-oss": "yarn oss-api && yarn notebooks && yarn unity && yarn annotations-oss && yarn pinned && yarn mapsd-oss && yarn cloudPriv",
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React, {FC, useContext} from 'react'
2+
import VersionBullet from 'src/flows/components/header/VersionBullet'
3+
import {VersionPublishContext} from 'src/flows/context/version.publish'
4+
5+
const PublishedVersions: FC = () => {
6+
const {versions} = useContext(VersionPublishContext)
7+
8+
if (versions.length === 0) {
9+
return null
10+
}
11+
12+
return (
13+
<>
14+
{versions.map(version => (
15+
<VersionBullet key={version.id} version={version} />
16+
))}
17+
</>
18+
)
19+
}
20+
21+
export default PublishedVersions
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.publish-version-bullet--button {
2+
margin-right: 40px;
3+
4+
&:hover {
5+
cursor: pointer;
6+
}
7+
}
8+
9+
.publish-version-bullet--button::before {
10+
content: '';
11+
height: 25px;
12+
width: 4px;
13+
transform: translate(-480%, 0%) rotate(-90deg);
14+
15+
@media screen and (max-width: $cf-grid--breakpoint-md) {
16+
transform: translate(-380%, 0%) rotate(-90deg);
17+
}
18+
background: #333346;
19+
background: -moz-linear-gradient(top, #333346 0%, #8e1fc3 100%);
20+
background: -webkit-linear-gradient(top, #333346 0%, #8e1fc3 100%);
21+
background: linear-gradient(to bottom, #333346 0%, #8e1fc3 100%);
22+
}
23+
24+
.publish-version--tooltip {
25+
padding: 10px;
26+
}
27+
28+
.publish-version-bullet--button::after {
29+
content: '';
30+
height: 25px;
31+
width: 4px;
32+
transform: translate(480%, 0) rotate(90deg);
33+
34+
@media screen and (max-width: $cf-grid--breakpoint-md) {
35+
transform: translate(380%, 0%) rotate(90deg);
36+
}
37+
background: #333346;
38+
background: -moz-linear-gradient(top, #333346 0%, #8e1fc3 100%);
39+
background: -webkit-linear-gradient(top, #333346 0%, #8e1fc3 100%);
40+
background: linear-gradient(to bottom, #333346 0%, #8e1fc3 100%);
41+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React, {createRef, FC, RefObject} from 'react'
2+
import {
3+
Appearance,
4+
Bullet,
5+
ComponentSize,
6+
IconFont,
7+
InfluxColors,
8+
Popover,
9+
PopoverInteraction,
10+
} from '@influxdata/clockface'
11+
12+
// Types
13+
import {VersionHistory} from 'src/client/notebooksRoutes'
14+
15+
type Props = {
16+
version: VersionHistory
17+
}
18+
19+
const VersionBullet: FC<Props> = ({version}) => {
20+
const triggerRef: RefObject<HTMLElement> = createRef()
21+
22+
const handleBulletClick = () => {
23+
// TODO(ariel): navigate to the version history based on the passed in version
24+
}
25+
26+
return (
27+
<>
28+
<div onClick={handleBulletClick}>
29+
<Bullet
30+
className="publish-version-bullet--button"
31+
glyph={IconFont.Checkmark_New}
32+
size={ComponentSize.Small}
33+
color={InfluxColors.White}
34+
backgroundColor={InfluxColors.Amethyst}
35+
ref={triggerRef}
36+
/>
37+
</div>
38+
<Popover
39+
appearance={Appearance.Outline}
40+
triggerRef={triggerRef}
41+
enableDefaultStyles={false}
42+
showEvent={PopoverInteraction.Hover}
43+
hideEvent={PopoverInteraction.Hover}
44+
contents={() => (
45+
<h6 className="publish-version--tooltip">
46+
Published by {version.publishedBy} at{' '}
47+
{new Date(version.publishedAt).toLocaleString()}
48+
</h6>
49+
)}
50+
/>
51+
</>
52+
)
53+
}
54+
55+
export default VersionBullet

src/flows/components/header/index.tsx

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ import React, {
99
RefObject,
1010
} from 'react'
1111
import {useHistory} from 'react-router-dom'
12-
import {useDispatch, useSelector} from 'react-redux'
12+
import {useSelector} from 'react-redux'
1313

1414
// Contexts
1515
import {FlowContext} from 'src/flows/context/flow.current'
1616
import {FlowListContext} from 'src/flows/context/flow.list'
17+
import {
18+
VersionPublishContext,
19+
VersionPublishProvider,
20+
} from 'src/flows/context/version.publish'
1721
import {AppSettingProvider} from 'src/shared/contexts/app'
1822
import {deletePinnedItemByParam} from 'src/shared/contexts/pinneditems'
1923

@@ -31,6 +35,7 @@ import {
3135
List,
3236
} from '@influxdata/clockface'
3337

38+
import PublishedVersions from 'src/flows/components/header/PublishedVersions'
3439
import AutoRefreshButton from 'src/flows/components/header/AutoRefreshButton'
3540
import TimeZoneDropdown from 'src/shared/components/TimeZoneDropdown'
3641
import TimeRangeDropdown from 'src/flows/components/header/TimeRangeDropdown'
@@ -46,18 +51,13 @@ import {
4651
getNotebooksShare,
4752
deleteNotebooksShare,
4853
postNotebooksShare,
49-
postNotebooksVersion,
5054
} from 'src/client/notebooksRoutes'
5155
import {event} from 'src/cloud/utils/reporting'
5256
import {downloadImage} from 'src/shared/utils/download'
5357
import {serialize} from 'src/flows/context/flow.list'
5458
import {updatePinnedItemByParam} from 'src/shared/contexts/pinneditems'
5559
import {getOrg} from 'src/organizations/selectors'
56-
import {notify} from 'src/shared/actions/notifications'
57-
import {
58-
publishNotebookFailed,
59-
publishNotebookSuccessful,
60-
} from 'src/shared/copy/notifications'
60+
6161
// Types
6262
import {RemoteDataState} from 'src/types'
6363

@@ -123,15 +123,12 @@ interface Share {
123123
}
124124

125125
const FlowHeader: FC = () => {
126-
const dispatch = useDispatch()
127126
const {remove, clone} = useContext(FlowListContext)
128127
const {flow, updateOther} = useContext(FlowContext)
128+
const {handlePublish, publishLoading} = useContext(VersionPublishContext)
129129
const history = useHistory()
130130
const {id: orgID} = useSelector(getOrg)
131131
const [sharing, setSharing] = useState(false)
132-
const [publishLoading, setPublishLoading] = useState<RemoteDataState>(
133-
RemoteDataState.NotStarted
134-
)
135132
const [share, setShare] = useState<Share>()
136133
const [linkLoading, setLinkLoading] = useState(RemoteDataState.NotStarted)
137134
const [linkDeleting, setLinkDeleting] = useState(RemoteDataState.NotStarted)
@@ -147,34 +144,12 @@ const FlowHeader: FC = () => {
147144
.catch(err => console.error('failed to get notebook share', err))
148145
}, [flow.id])
149146

150-
const handlePublish = useCallback(async () => {
151-
if (isFlagEnabled('flowPublishLifecycle')) {
152-
setPublishLoading(RemoteDataState.Loading)
153-
try {
154-
const response = await postNotebooksVersion({id: flow.id})
155-
156-
if (response.status !== 204) {
157-
throw new Error(response.data.message)
158-
}
159-
160-
dispatch(notify(publishNotebookSuccessful(flow.name)))
161-
setPublishLoading(RemoteDataState.Done)
162-
} catch (error) {
163-
console.error({error})
164-
dispatch(notify(publishNotebookFailed(flow.name)))
165-
setPublishLoading(RemoteDataState.Error)
166-
}
167-
}
168-
}, [dispatch, flow.id, flow.name])
169-
170147
const handleSave = useCallback(
171148
event => {
149+
event.preventDefault()
172150
if (isFlagEnabled('flowPublishLifecycle')) {
173151
if ((event.ctrlKey || event.metaKey) && event.key === 's') {
174-
// Prevent the Save dialog to open
175-
event.preventDefault()
176152
handlePublish()
177-
// Place your code here
178153
}
179154
}
180155
},
@@ -453,6 +428,13 @@ const FlowHeader: FC = () => {
453428
</Page.ControlBarRight>
454429
</Page.ControlBar>
455430
)}
431+
{isFlagEnabled('flowPublishLifecycle') && (
432+
<Page.ControlBar fullWidth>
433+
<Page.ControlBarRight>
434+
<PublishedVersions />
435+
</Page.ControlBarRight>
436+
</Page.ControlBar>
437+
)}
456438
{!!sharing && !!share && (
457439
<Page.ControlBar fullWidth>
458440
<Page.ControlBarRight>
@@ -496,6 +478,8 @@ const FlowHeader: FC = () => {
496478

497479
export default () => (
498480
<AppSettingProvider>
499-
<FlowHeader />
481+
<VersionPublishProvider>
482+
<FlowHeader />
483+
</VersionPublishProvider>
500484
</AppSettingProvider>
501485
)
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Libraries
2+
import React, {
3+
FC,
4+
createContext,
5+
useCallback,
6+
useContext,
7+
useEffect,
8+
useState,
9+
} from 'react'
10+
import {useDispatch} from 'react-redux'
11+
12+
// Context
13+
import {FlowContext} from 'src/flows/context/flow.current'
14+
15+
// Utils
16+
import {
17+
getNotebooksVersions,
18+
postNotebooksVersion,
19+
VersionHistories,
20+
} from 'src/client/notebooksRoutes'
21+
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
22+
import {notify} from 'src/shared/actions/notifications'
23+
import {
24+
publishNotebookFailed,
25+
publishNotebookSuccessful,
26+
} from 'src/shared/copy/notifications'
27+
28+
// Types
29+
import {RemoteDataState} from 'src/types'
30+
31+
interface ContextType {
32+
handlePublish: () => void
33+
publishLoading: RemoteDataState
34+
versions: VersionHistories
35+
}
36+
37+
const DEFAULT_CONTEXT: ContextType = {
38+
handlePublish: () => {},
39+
publishLoading: RemoteDataState.NotStarted,
40+
versions: [],
41+
}
42+
43+
export const VersionPublishContext = createContext<ContextType>(DEFAULT_CONTEXT)
44+
45+
export const VersionPublishProvider: FC = ({children}) => {
46+
const {flow} = useContext(FlowContext)
47+
const dispatch = useDispatch()
48+
const [versions, setVersions] = useState([])
49+
const [publishLoading, setPublishLoading] = useState<RemoteDataState>(
50+
RemoteDataState.NotStarted
51+
)
52+
53+
const handleGetNotebookVersions = useCallback(async () => {
54+
try {
55+
const response = await getNotebooksVersions({id: flow.id})
56+
57+
if (response.status !== 200) {
58+
throw new Error(response.data.message)
59+
}
60+
61+
setVersions(response.data)
62+
} catch (error) {
63+
console.error({error})
64+
}
65+
}, [flow.id])
66+
67+
useEffect(() => {
68+
if (isFlagEnabled('flowPublishLifecycle')) {
69+
handleGetNotebookVersions()
70+
}
71+
}, [handleGetNotebookVersions])
72+
73+
const handlePublish = useCallback(async () => {
74+
try {
75+
const response = await postNotebooksVersion({id: flow.id})
76+
77+
if (response.status !== 200) {
78+
throw new Error(response.data.message)
79+
}
80+
81+
dispatch(notify(publishNotebookSuccessful(flow.name)))
82+
setPublishLoading(RemoteDataState.Done)
83+
handleGetNotebookVersions()
84+
} catch (error) {
85+
dispatch(notify(publishNotebookFailed(flow.name)))
86+
setPublishLoading(RemoteDataState.Error)
87+
}
88+
}, [dispatch, handleGetNotebookVersions, flow.id, flow.name])
89+
90+
return (
91+
<VersionPublishContext.Provider
92+
value={{
93+
handlePublish,
94+
publishLoading,
95+
versions,
96+
}}
97+
>
98+
{children}
99+
</VersionPublishContext.Provider>
100+
)
101+
}

src/style/chronograf.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@
142142
@import 'src/buckets/components/createBucketForm/MeasurementSchema.scss';
143143
@import 'src/writeData/components/AddPluginToConfiguration.scss';
144144
@import 'src/authorizations/components/customApiTokenOverlay.scss';
145+
@import 'src/flows/components/header/VersionBullet.scss';
145146

146147
// External
147148
@import '../../node_modules/@influxdata/react-custom-scrollbars/dist/styles.css';

0 commit comments

Comments
 (0)