Skip to content

Commit 9438718

Browse files
feat: unpinning an item from the resource location (#4019)
* feat: enable to unpin a notebook from notebooks page * feat: hide the popover when pinned a task or a dashboard * feat: enable to unpin a task * feat: enable to unpin a dashboard * chore: update comments to be clear * chore: add window.location.reload in task card * fix: update pinned item list after a task is just pinned * fix: update pinned item list after a dashboard is just pinned * fix: add onPinTask in TaskCard.test.tsx * refactor: change function name to onPinDashboard * refactor: move code into onAddPinnedItem and onDeletePinnedItem * refactor: move code into handleAddPinnedItem and handleDeletePinnedItem * refactor: move duplicated code into the same function * refactor: move unpin logic to parents - DashboardCards and DashboardCardsPaginated * refactor: move pin logic to parents - DashboardCards and DashboardCardsPaginated * refactor: move unpin logic to parent - TasksList * refactor: move pin logic to parent - TasksList * test: fix missing function declaration * fix: remove async away from the func that did not use await
1 parent 9c7a27e commit 9438718

File tree

7 files changed

+312
-103
lines changed

7 files changed

+312
-103
lines changed

src/dashboards/components/dashboard_index/DashboardCard.tsx

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,10 @@ import {
4747
import {notify} from 'src/shared/actions/notifications'
4848

4949
import {
50-
addPinnedItem,
5150
deletePinnedItemByParam,
52-
PinnedItemTypes,
5351
updatePinnedItemByParam,
5452
} from 'src/shared/contexts/pinneditems'
5553

56-
import {getMe} from 'src/me/selectors'
57-
import {getOrg} from 'src/organizations/selectors'
5854
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
5955
import {CLOUD} from 'src/shared/constants'
6056
import {PROJECT_NAME} from 'src/flows'
@@ -66,6 +62,12 @@ interface OwnProps {
6662
updatedAt: string
6763
labels: string[]
6864
onFilterChange: (searchTerm: string) => void
65+
onPinDashboard: (
66+
dashboardID: string,
67+
name: string,
68+
description: string
69+
) => void
70+
onUnpinDashboard: (DashboardID: string) => void
6971
isPinned: boolean
7072
}
7173

@@ -129,7 +131,7 @@ class DashboardCard extends PureComponent<Props> {
129131
updatePinnedItemByParam(id, {name})
130132
this.props.sendNotification(pinnedItemSuccess('dashboard', 'updated'))
131133
} catch (err) {
132-
this.props.sendNotification(pinnedItemFailure(err.message, 'dashboard'))
134+
this.props.sendNotification(pinnedItemFailure(err.message, 'update'))
133135
}
134136
}
135137
}
@@ -141,21 +143,11 @@ class DashboardCard extends PureComponent<Props> {
141143
}
142144

143145
private handlePinDashboard = () => {
144-
try {
145-
addPinnedItem({
146-
orgID: this.props.org.id,
147-
userID: this.props.me.id,
148-
metadata: {
149-
dashboardID: this.props.id,
150-
name: this.props.name,
151-
description: this.props.description,
152-
},
153-
154-
type: PinnedItemTypes.Dashboard,
155-
})
156-
this.props.sendNotification(pinnedItemSuccess('dashboard', 'added'))
157-
} catch (err) {
158-
this.props.sendNotification(pinnedItemFailure(err.message, 'dashboard'))
146+
const {id, name, description, isPinned} = this.props
147+
if (isPinned) {
148+
this.props.onUnpinDashboard(id)
149+
} else {
150+
this.props.onPinDashboard(id, name, description)
159151
}
160152
}
161153

@@ -185,7 +177,7 @@ class DashboardCard extends PureComponent<Props> {
185177
appearance={Appearance.Outline}
186178
enableDefaultStyles={false}
187179
style={minWidth}
188-
contents={() => (
180+
contents={onHide => (
189181
<List>
190182
<List.Item
191183
onClick={this.handleExport}
@@ -205,13 +197,15 @@ class DashboardCard extends PureComponent<Props> {
205197
</List.Item>
206198
{isFlagEnabled('pinnedItems') && CLOUD && (
207199
<List.Item
208-
onClick={this.handlePinDashboard}
209-
disabled={this.props.isPinned}
200+
onClick={() => {
201+
this.handlePinDashboard()
202+
onHide()
203+
}}
210204
size={ComponentSize.Small}
211205
style={fontWeight}
212206
testID="context-pin-dashboard"
213207
>
214-
Pin
208+
{this.props.isPinned ? 'Unpin' : 'Pin'}
215209
</List.Item>
216210
)}
217211
</List>
@@ -260,7 +254,7 @@ class DashboardCard extends PureComponent<Props> {
260254
try {
261255
updatePinnedItemByParam(id, {description})
262256
} catch (err) {
263-
this.props.sendNotification(pinnedItemFailure(err.message, 'dashboard'))
257+
this.props.sendNotification(pinnedItemFailure(err.message, 'update'))
264258
}
265259
}
266260

@@ -293,13 +287,9 @@ const mdtp = {
293287

294288
const mstp = (state: AppState, props: OwnProps) => {
295289
const dashboard = state.resources.dashboards.byID[props.id]
296-
const me = getMe(state)
297-
const org = getOrg(state)
298290

299291
return {
300292
dashboard,
301-
me,
302-
org,
303293
}
304294
}
305295
const connector = connect(mstp, mdtp)

src/dashboards/components/dashboard_index/DashboardCards.tsx

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Libraries
22
import React, {PureComponent} from 'react'
3-
import {connect} from 'react-redux'
3+
import {connect, ConnectedProps} from 'react-redux'
44
import memoizeOne from 'memoize-one'
55

66
// Components
@@ -10,16 +10,31 @@ import AssetLimitAlert from 'src/cloud/components/AssetLimitAlert'
1010

1111
// Selectors
1212
import {getSortedResources, SortTypes} from 'src/shared/utils/sort'
13+
import {getMe} from 'src/me/selectors'
14+
import {getOrg} from 'src/organizations/selectors'
1315

1416
// Types
1517
import {AppState, Dashboard, RemoteDataState} from 'src/types'
1618
import {Sort} from 'src/clockface'
1719
import {LimitStatus} from 'src/cloud/actions/limits'
1820

21+
// Contexts
22+
import {
23+
addPinnedItem,
24+
deletePinnedItemByParam,
25+
PinnedItemTypes,
26+
} from 'src/shared/contexts/pinneditems'
27+
1928
// Utils
2029
import {extractDashboardLimits} from 'src/cloud/utils/limits'
2130
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
2231
import {CLOUD} from 'src/shared/constants'
32+
import {notify} from 'src/shared/actions/notifications'
33+
34+
import {
35+
pinnedItemFailure,
36+
pinnedItemSuccess,
37+
} from 'src/shared/copy/notifications'
2338

2439
let getPinnedItems
2540
if (CLOUD) {
@@ -38,7 +53,10 @@ interface OwnProps {
3853
onFilterChange: (searchTerm: string) => void
3954
}
4055

41-
class DashboardCards extends PureComponent<OwnProps & StateProps> {
56+
type ReduxProps = ConnectedProps<typeof connector>
57+
type Props = OwnProps & StateProps & ReduxProps
58+
59+
class DashboardCards extends PureComponent<Props> {
4260
private _observer
4361
private _isMounted = true
4462
private _spinner
@@ -55,18 +73,9 @@ class DashboardCards extends PureComponent<OwnProps & StateProps> {
5573

5674
public componentDidMount() {
5775
if (isFlagEnabled('pinnedItems') && CLOUD) {
58-
getPinnedItems()
59-
.then(res => {
60-
if (this._isMounted) {
61-
this.setState(prev => ({...prev, pinnedItems: res, windowSize: 15}))
62-
}
63-
})
64-
.catch(err => {
65-
console.error(err)
66-
})
67-
} else {
68-
this.setState(prev => ({...prev, windowSize: 15}))
76+
this.updatePinnedItems()
6977
}
78+
this.setState(prev => ({...prev, windowSize: 15}))
7079
}
7180

7281
public componentWillUnmount() {
@@ -110,6 +119,53 @@ class DashboardCards extends PureComponent<OwnProps & StateProps> {
110119
}
111120
}
112121

122+
public updatePinnedItems = () => {
123+
getPinnedItems()
124+
.then(res => {
125+
if (this._isMounted) {
126+
this.setState(prev => ({...prev, pinnedItems: res}))
127+
}
128+
})
129+
.catch(err => console.error(err))
130+
}
131+
132+
public handlePinDashboard = async (
133+
dashboardID: string,
134+
name: string,
135+
description: string
136+
) => {
137+
const {org, me} = this.props
138+
139+
// add to pinned item list
140+
try {
141+
await addPinnedItem({
142+
orgID: org.id,
143+
userID: me.id,
144+
metadata: {
145+
dashboardID,
146+
name,
147+
description,
148+
},
149+
type: PinnedItemTypes.Dashboard,
150+
})
151+
this.props.sendNotification(pinnedItemSuccess('dashboard', 'added'))
152+
this.updatePinnedItems()
153+
} catch (err) {
154+
this.props.sendNotification(pinnedItemFailure(err.message, 'add'))
155+
}
156+
}
157+
158+
public handleUnpinDashboard = async (dashboardID: string) => {
159+
// delete from pinned item list
160+
try {
161+
await deletePinnedItemByParam(dashboardID)
162+
this.props.sendNotification(pinnedItemSuccess('dashboard', 'deleted'))
163+
this.updatePinnedItems()
164+
} catch (err) {
165+
this.props.sendNotification(pinnedItemFailure(err.message, 'delete'))
166+
}
167+
}
168+
113169
public render() {
114170
const {
115171
dashboards,
@@ -142,6 +198,8 @@ class DashboardCards extends PureComponent<OwnProps & StateProps> {
142198
updatedAt={meta.updatedAt}
143199
description={description}
144200
onFilterChange={onFilterChange}
201+
onPinDashboard={this.handlePinDashboard}
202+
onUnpinDashboard={this.handleUnpinDashboard}
145203
isPinned={
146204
!!pinnedItems.find(item => item?.metadata.dashboardID === id)
147205
}
@@ -166,10 +224,21 @@ class DashboardCards extends PureComponent<OwnProps & StateProps> {
166224
}
167225
}
168226

227+
const mdtp = {
228+
sendNotification: notify,
229+
}
230+
169231
const mstp = (state: AppState) => {
232+
const me = getMe(state)
233+
const org = getOrg(state)
234+
170235
return {
171236
limitStatus: extractDashboardLimits(state),
237+
me,
238+
org,
172239
}
173240
}
174241

175-
export default connect(mstp)(DashboardCards)
242+
const connector = connect(mstp, mdtp)
243+
244+
export default connector(DashboardCards)

0 commit comments

Comments
 (0)