Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HelpScout suggestions #804

Merged
merged 19 commits into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
34c4e12
useBeaconSuggestions: add hook to suggest articles based on location
AquiGorka May 27, 2019
cdf9c5c
App: add locator and apps props to helpscout beacon
AquiGorka May 27, 2019
2494619
HelpScoutBeacon: add suggestions hook
AquiGorka May 27, 2019
1808075
useBeaconSuggestion: add useCallback hook improvements
AquiGorka May 27, 2019
3fd58ba
useBeaconSuggestion: remove unnecessary react import
AquiGorka May 27, 2019
a2631fc
HelpScoutBeacon: fix prop types
AquiGorka May 27, 2019
34ef602
useBeaconSuggestion: fix array loop
AquiGorka May 27, 2019
090dc74
HelpScoutBeacon: use correct prop type for apps
AquiGorka May 28, 2019
ca364c0
HelpScoutBeacon: add suggestions map as json
AquiGorka May 28, 2019
2869c84
useBeaconSuggestions: use map from json file
AquiGorka May 28, 2019
0540319
useBeaconSuggestion: remove optedIn prop
AquiGorka May 28, 2019
5f389b9
HelpScoutBeacon: remove optedIn arg
AquiGorka May 28, 2019
74d097d
useBeaconSuggestion: use staticApps map in check
AquiGorka May 28, 2019
c8245c0
HelpScoutBeacon: add back optedIn prop
AquiGorka May 28, 2019
b967dfa
useBeaconSuggestion: set flow to avoid race condition on opt-in
AquiGorka May 28, 2019
bfafe6e
Move json file to js to be able to add comments
AquiGorka May 28, 2019
a389348
useBeaconSuggestion: use data from js file
AquiGorka May 28, 2019
d3ff3c4
useBeaconSuggestions: add cleanup to timeout effect
AquiGorka May 29, 2019
2972a08
useBeaconSuggestions: remove canSuggest state as it is always in sync…
AquiGorka May 29, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ class App extends React.Component {
/>
</div>

<HelpScoutBeacon />
<HelpScoutBeacon locator={locator} apps={apps} />
</ActivityProvider>
</FavoriteDaosProvider>
</LocalIdentityModalProvider>
Expand Down
11 changes: 10 additions & 1 deletion src/components/HelpScoutBeacon/HelpScoutBeacon.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import {
theme,
useViewport,
} from '@aragon/ui'
import useBeaconSuggestions from './useBeaconSuggestions'
import BeaconHeadScripts from './BeaconHeadScripts'
import IconQuestion from './IconQuestion'
import headerImg from './header.png'
import { useClickOutside } from '../../hooks'
import LoadingRing from '../LoadingRing'
import { GU } from '../../utils'
import { AppType } from '../../prop-types'

const HELPSCOUT_BEACON_KEY = 'helpscout-beacon'
const CLOSED = Symbol('closed, user can open opt-in dialogue')
Expand All @@ -26,7 +28,7 @@ const OPENING = Symbol('opening')
const CLOSING = Symbol('closing')
const ROUND_BUTTON_HEIGHT = 40

const Beacon = React.memo(function Beacon() {
const Beacon = React.memo(function Beacon({ locator, apps }) {
const [beaconReady, setBeaconReady] = useState(false)
const [openOnReady, setOpenOnReady] = useState(false)
const [optedIn, setOptedIn] = useState(
Expand All @@ -50,6 +52,8 @@ const Beacon = React.memo(function Beacon() {
}
}, [openOnReady])

useBeaconSuggestions({ apps, locator, optedIn, beaconReady })

return (
<div
css={`
Expand Down Expand Up @@ -78,6 +82,11 @@ const Beacon = React.memo(function Beacon() {
)
})

Beacon.propTypes = {
apps: PropTypes.arrayOf(AppType),
locator: PropTypes.object,
}

const HelpOptIn = React.memo(function HelpOptIn({
beaconReady,
onOptIn,
Expand Down
68 changes: 68 additions & 0 deletions src/components/HelpScoutBeacon/suggestions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const aboutAragon = '5c98a9330428633d2cf3fd23'

const suggestions = [
[
'home',
[
'5cce35302c7d3a177d6e5b78', // home
'5cce3c4c2c7d3a177d6e5ba2', // troubleshoot
'5cce34a32c7d3a177d6e5b74', // about aragon apps
'5cce259a2c7d3a177d6e5b33', // anatomy of association
aboutAragon,
],
],
[
'settings',
[
'5cce3bd204286306738eb793', // settings
aboutAragon,
],
],
[
'apps',
[
'5cce3baf04286306738eb792', // apps
aboutAragon,
],
],
[
'permissions',
[
'5cce3a7104286306738eb788', // permissions
aboutAragon,
],
],
[
'onboarding',
[
'5cce262f2c7d3a177d6e5b36', // prerequisites
'5cce28e82c7d3a177d6e5b40', // about templates
'5cce29a72c7d3a177d6e5b46', // create new democracy
'5cce2f0f2c7d3a177d6e5b5a', // creeate multisig
aboutAragon,
],
],
[
'finance',
[
'5cce39b32c7d3a177d6e5b8b', // finance
aboutAragon,
],
],
[
'token manager',
[
'5cce38892c7d3a177d6e5b84', // token manager
aboutAragon,
],
],
[
'voting',
[
'5cce393a2c7d3a177d6e5b87', // voting
aboutAragon,
],
],
]

export default suggestions
53 changes: 53 additions & 0 deletions src/components/HelpScoutBeacon/useBeaconSuggestions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useEffect, useCallback, useState } from 'react'
import suggestions from './suggestions'
import { staticApps } from '../../static-apps'

const sectionToSuggestions = new Map(suggestions)

function useBeaconSuggestions({
apps,
beaconReady,
locator: { instanceId, path },
optedIn,
}) {
const [originalOptedIn] = useState(optedIn)
const [shouldSuggest, setShouldSuggest] = useState(false)
const getSection = useCallback(() => {
if (path === '/') {
return 'onboarding'
}
if (staticApps.has(instanceId)) {
return instanceId
}
const app = apps.find(({ proxyAddress }) => proxyAddress === instanceId)
if (app) {
return app.name.toLowerCase()
}
return null
}, [path, instanceId, apps])

useEffect(() => {
if (!shouldSuggest) {
return
}
window.Beacon('suggest', sectionToSuggestions.get(getSection()))
}, [getSection, shouldSuggest])

useEffect(() => {
if (!optedIn || !beaconReady) {
return
}
// this only happens when user opts in
// when opting in beaconReady is set after the open event has been triggered
// give it a minute before suggesting or a weird reace condition happens
let timeout
if (!originalOptedIn) {
timeout = setTimeout(() => setShouldSuggest(true), 1000)
return
}
setShouldSuggest(true)
return () => clearTimeout(timeout)
}, [optedIn, beaconReady, originalOptedIn])
}

export default useBeaconSuggestions