lodash#defer JavaScript Examples
The following examples show how to use
lodash#defer.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Canvas.js From hivemind with Apache License 2.0 | 4 votes |
Canvas = ({ data, timestamp, events }) => {
const { cyWrapper, poppers } = useContext(GlobalContext)
const [output, setOutput] = useState(null)
const [els, setEls] = useState([])
const prevEls = usePrevious(els)
useEffect(() => {
if (cyWrapper.cy && prevEls !== els) {
const commonEls = intersectionBy(prevEls, els, 'data.id')
const celMap = zipObject(map(commonEls, 'data.id'), commonEls)
cyWrapper.cy
.elements()
.filter((el) => celMap[el.id()])
.forEach((el) => {
el.removeData('summary content audio lastUpdatedBy')
el.data(celMap[el.id()].data)
})
}
}, [cyWrapper.cy, els, prevEls])
useEffect(() => {
if (get(data, 'ok') && typeof window !== 'undefined') {
setEls(CytoscapeComponent.normalizeElements(data.data.elements))
}
}, [data])
useEffect(() => {
function initCy(cyInternal) {
cyWrapper.cy = cyInternal
cyInternal.nodes().forEach((node) => {
node.scratch('style', node.style())
})
}
const nodes = els.filter((el) => !el.data.id.startsWith('links'))
const fit = shouldFit(nodes)
const options = getOptions(fit)
setOutput(
<CytoscapeComponent
cy={initCy}
style={{ width: '100%', height: '100%' }}
stylesheet={style}
layout={options}
elements={els}
/>
)
}, [cyWrapper, els])
useEffect(() => {
function configurePlugins(access) {
function buildMenu() {
const { viewApi } = cyWrapper
return function (node) {
const menu = []
view(menu, poppers)
if (!node.data('isRoot')) {
hide(menu, viewApi)
}
if (node.scratch('showReveal')) {
reveal(menu, viewApi)
}
if (access && ['admin', 'write'].includes(access.access)) {
add(menu, poppers)
if (!node.data('isRoot')) {
del(menu, poppers)
}
edit(menu, poppers)
}
return menu
}
}
const { cy } = cyWrapper
const minRadius = Math.min(cy.width(), cy.height()) / 8
const viewOpts = {
highlightStyles: [
{
node: { 'border-color': '#0b9bcd', 'border-width': 3 },
edge: {
'line-color': '#0b9bcd',
'source-arrow-color': '#0b9bcd',
'target-arrow-color': '#0b9bcd',
width: 3,
},
},
{
node: { 'border-color': '#04f06a', 'border-width': 3 },
edge: {
'line-color': '#04f06a',
'source-arrow-color': '#04f06a',
'target-arrow-color': '#04f06a',
width: 3,
},
},
],
selectStyles: {
node: {
'border-color': 'white',
'border-width': 3,
'background-color': 'lightgrey',
},
edge: {
'line-color': 'white',
'source-arrow-color': 'white',
'target-arrow-color': 'white',
width: 3,
},
},
setVisibilityOnHide: false, // whether to set visibility on hide/show
setDisplayOnHide: true, // whether to set display on hide/show
zoomAnimationDuration: 500, //default duration for zoom animation speed
neighbor: function (node) {
return node.successors()
},
neighborSelectTime: 500,
}
cyWrapper.viewApi = cy.viewUtilities(viewOpts)
const cxtMenu = {
menuRadius: minRadius + 50, // the radius of the circular menu in pixels
selector: 'node', // elements matching this Cytoscape.js selector will trigger cxtmenus
commands: buildMenu(), // function( ele ){ return [
// /*...*/ ] }, // a function
// that returns
// commands or a promise of commands
fillColor: 'rgba(0, 0, 0, 0.75)', // the background colour of the menu
activeFillColor: 'rgba(100, 100, 100, 0.5)', // the colour used to indicate the selected
// command
activePadding: 10, // additional size in pixels for the active command
indicatorSize: 16, // the size in pixels of the pointer to the active command
separatorWidth: 3, // the empty spacing in pixels between successive commands
spotlightPadding: 4, // extra spacing in pixels between the element and the spotlight
minSpotlightRadius: minRadius - 40, // the minimum radius in pixels of the spotlight
maxSpotlightRadius: minRadius - 20, // the maximum radius in pixels of the spotlight
openMenuEvents: 'tap', // space-separated cytoscape events that will open the menu; only
// `cxttapstart` and/or `taphold` work here
itemColor: 'white', // the colour of text in the command's content
itemTextShadowColor: 'transparent', // the text shadow colour of the command's content
// zIndex: 9999, // the z-index of the ui div
atMouse: false, // draw menu at mouse position
}
cyWrapper.menu = cy.cxtmenu(cxtMenu)
}
function setHandlers() {
const { viewApi, cy } = cyWrapper
cy.on(
'boxend',
throttle(() => defer(() => viewApi.zoomToSelected(cy.$(':selected')))),
1000
)
cy.on('mouseover', 'node', () => {
document.getElementById('cy').style.cursor = 'pointer'
})
cy.on('mouseout', 'node', () => {
document.getElementById('cy').style.cursor = 'default'
})
cy.on('mouseover', 'edge', (e) => {
e.target.style({
width: 4,
'line-color': '#007bff',
'target-arrow-color': '#007bff',
})
})
cy.on('unselect mouseout', 'edge', (e) => {
const edge = e.target
if (!edge.selected()) {
edge.style({
width: 2,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
})
}
})
cy.on('add', 'node', (e) => {
const node = e.target
node.scratch('style', node.style())
})
cy.on(
'add data remove',
'node',
throttle(() => {
if (timestamp) {
const idx = findIndex(events.data, { lctime: timestamp })
const event = events.data[idx]
const { viewApi } = cyWrapper
viewApi.removeHighlights(cy.elements())
if (event && event.event !== 'deleted') {
const nid = event.nids[0]
const node = cy.$id(nid)
viewApi.highlight(node)
}
}
}, 100)
)
cy.on('mouseover', 'node', (e) => {
e.target.style('background-color', '#007bff')
})
cy.on('unselect mouseout', 'node', (e) => {
const node = e.target
viewApi.removeHighlights(node)
if (!node.selected()) {
node.style(
'background-color',
node.scratch('style')['background-color']
)
}
})
}
if (cyWrapper.cy && get(data, 'ok') && get(events, 'ok')) {
configurePlugins(data.data.access)
setHandlers()
}
return () => {
if (cyWrapper.menu) {
cyWrapper.menu.destroy()
}
}
}, [data, events, cyWrapper.menu, cyWrapper, timestamp, poppers, els])
return (
<div
className={`border border-${
timestamp ? 'secondary' : 'danger'
} rounded w-100`}
id="cy-container"
>
<div className="m-1" id="cy">
{output}
</div>
</div>
)
}
Example #2
Source File: Timeline.js From hivemind with Apache License 2.0 | 4 votes |
Timeline = ({ data, timestamp, jump }) => {
const timelineRef = useRef()
const timeline = useRef()
const {
cyWrapper: { cy, viewApi },
} = useContext(GlobalContext)
const [modal, setModal] = useState(false)
const [target, setTarget] = useState('timeline')
const [node, setNode] = useState(<Spinner />)
const [showJump, setShowJump] = useState('d-block')
const [showFind, setShowFind] = useState('d-none')
const [items, setItems] = useState([])
const toggle = () => setModal(!modal)
const jumpTo = async (lctime) => {
if (lctime !== timestamp) {
jump(lctime)
}
setModal(false)
}
const locate = (item) => {
if (item && item.event !== 'deleted') {
const node = cy.$id(item.nid)
viewApi.zoomToSelected(node)
viewApi.removeHighlights(cy.elements())
viewApi.highlight(node)
}
setModal(false)
}
useEffect(() => {
if (get(data, 'ok')) {
setItems(
data.data.map((event, idx) => ({
id: idx,
className: event.lctime === timestamp ? 'pinned' : '',
title: event.event,
content: '',
start: event.lctime * 1000,
style: `background-color: ${bgColors[event.event]};`,
lctime: event.lctime,
nid: event.nids[0] || event.mid,
event: event.event,
}))
)
}
}, [data, timestamp])
useEffect(() => {
if (items.length) {
if (timeline.current) {
timeline.current.setItems(items)
} else {
const container = timelineRef.current
if (container.firstChild) {
container.removeChild(container.firstChild)
}
const margin = (items[items.length - 1].start - items[0].start) * 0.05
const options = {
width: '100%',
height: '120px',
type: 'box',
stack: false,
horizontalScroll: false,
verticalScroll: false,
cluster: {
titleTemplate: '{count}',
maxItems: 1,
showStipes: true,
fitOnDoubleClick: true,
},
max: items[items.length - 1].start + margin,
min: items[0].start - margin,
selectable: false,
dataAttributes: ['id'],
zoomMin: 60000,
}
timeline.current = new VisTimeline(container, items, options)
}
timeline.current.on('click', (properties) => {
const { what, isCluster, item } = properties
if (what === 'item' && !isCluster) {
setNode(<Spinner />)
setTarget(item)
setModal(true)
if (items[item].className === 'pinned') {
setShowJump('d-none')
if (items[item].event !== 'deleted') {
setShowFind('d-block')
}
} else {
setShowJump('d-block')
setShowFind('d-none')
}
} else {
setModal(false)
setTarget('timeline')
}
})
timeline.current.on('doubleClick', (properties) => {
const { what, item, isCluster } = properties
switch (what) {
case 'background':
timeline.current.fit()
break
case 'item':
if (!isCluster) {
timeline.current.focus(item)
}
break
}
})
defer(() => { // To ensure focus/fit on first load.
if (timestamp) {
const idx = findIndex(items, { lctime: timestamp })
timeline.current.focus(idx)
} else {
timeline.current.fit()
}
})
}
}, [items, timestamp])
useEffect(
() => () => {
timeline.current.destroy()
timeline.current = null
},
[]
)
return (
<div className={'border border-secondary rounded'}>
<div id={'timeline'} ref={timelineRef} className={'m-1'} >
<Spinner/>
</div>
<Modal
isOpen={modal}
toggle={toggle}
fade={false}
centered={true}
size={'lg'}
scrollable={true}
>
<ModalHeader toggle={toggle}>
<b>{node}</b> | {get(items, [target, 'event'], 'NA')}{' '}
{new Date(get(items, [target, 'start'], Date.now())).toLocaleString()}
</ModalHeader>
<ModalBody>
{data && data.data[target] ? (
<EventDetail event={data.data[target]} setNode={setNode} />
) : null}
</ModalBody>
<ModalFooter>
<Button
className={`ml-1 ${showJump}`}
outline
color="secondary"
id="jump"
onClick={() => jumpTo(items[target].lctime)}
>
<MapPin size={16} /> Jump
</Button>
<Button
className={`ml-1 ${showFind}`}
outline
color="secondary"
id="find"
onClick={() => locate(items[target])}
>
<Search size={16} /> Find
</Button>
<ToolTippedButton
className="ml-1"
outline
color="secondary"
id="tag"
disabled={true}
tooltip={'Coming Soon'}
>
<Tag size={16} /> Tag
</ToolTippedButton>
</ModalFooter>
</Modal>
</div>
)
}