Skip to content

Commit

Permalink
Add trigger and target element logs for devtools (#276)
Browse files Browse the repository at this point in the history
# Enhancement

## Description

Furnishes cable-ready-updates-for-element with instance variables for
element logs, so they can displayed in the devtools like this:

![CleanShot 2023-05-08 at 12 22
44@2x](https://user-images.githubusercontent.com/4352208/236800677-53feffad-3dc5-4159-8483-4dadf86236d4.png)
  • Loading branch information
julianrubisch committed Jun 23, 2023
1 parent 9da5cfe commit d4b8364
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 23 deletions.
49 changes: 41 additions & 8 deletions javascript/elements/updates_for_element.js
Expand Up @@ -7,6 +7,7 @@ import { debounce, assignFocus, dispatch, graciouslyFetch } from '../utils'
import ActiveElement from '../active_element'
import CableConsumer from '../cable_consumer'
import Log from '../updatable/log'
import { BoundedQueue } from '../utils'

const template = `
<style>
Expand All @@ -32,6 +33,9 @@ export default class UpdatesForElement extends SubscribingElement {
super()
const shadowRoot = this.attachShadow({ mode: 'open' })
shadowRoot.innerHTML = template

this.triggerElementLog = new BoundedQueue(10)
this.targetElementLog = new BoundedQueue(10)
}

async connectedCallback () {
Expand All @@ -57,17 +61,29 @@ export default class UpdatesForElement extends SubscribingElement {
element => new Block(element)
).filter(block => block.shouldUpdate(data))

Log.request(data, blocks)
this.triggerElementLog.push(
`${new Date().toLocaleString()}: ${Log.request(data, blocks)}`
)

if (blocks.length === 0) {
Log.cancel(this.lastUpdateTimestamp, 'All elements filtered out')
this.triggerElementLog.push(
`${new Date().toLocaleString()}: ${Log.cancel(
this.lastUpdateTimestamp,
'All elements filtered out'
)}`
)

return
}

// first <cable-ready-updates-for> element in the DOM *at any given moment* updates all of the others
if (blocks[0].element !== this) {
Log.cancel(this.lastUpdateTimestamp, 'Update already requested')
this.triggerElementLog.push(
`${new Date().toLocaleString()}: ${Log.cancel(
this.lastUpdateTimestamp,
'Update already requested'
)}`
)

return
}
Expand All @@ -91,7 +107,13 @@ export default class UpdatesForElement extends SubscribingElement {
})
)

Log.response(this.lastUpdateTimestamp, this, uniqueUrls)
this.triggerElementLog.push(
`${new Date().toLocaleString()}: ${Log.response(
this.lastUpdateTimestamp,
this,
uniqueUrls
)}`
)

// track current block index for each URL; referred to as fragments
this.index = {}
Expand Down Expand Up @@ -126,8 +148,8 @@ class Block {
this.element = element
}

async process (data, html, index, startTimestamp) {
const blockIndex = index[this.url]
async process (data, html, fragmentsIndex, startTimestamp) {
const blockIndex = fragmentsIndex[this.url]
const template = document.createElement('template')
this.element.setAttribute('updating', 'updating')

Expand All @@ -151,7 +173,12 @@ class Block {
}

dispatch(this.element, 'cable-ready:before-update', operation)
Log.morphStart(startTimestamp, this.element)
this.element.targetElementLog.push(
`${new Date().toLocaleString()}: ${Log.morphStart(
startTimestamp,
this.element
)}`
)

morphdom(this.element, fragments[blockIndex], {
childrenOnly: true,
Expand All @@ -162,7 +189,13 @@ class Block {
assignFocus(operation.focusSelector)
}
})
Log.morphEnd(startTimestamp, this.element)

this.element.targetElementLog.push(
`${new Date().toLocaleString()}: ${Log.morphEnd(
startTimestamp,
this.element
)}`
)
}

async resolveTurboFrames (documentFragment) {
Expand Down
42 changes: 28 additions & 14 deletions javascript/updatable/log.js
Expand Up @@ -3,51 +3,65 @@ import Debug from '../debug'
const request = (data, blocks) => {
if (Debug.disabled) return

console.log(
`\u2191 Updatable request affecting ${blocks.length} element(s): `,
{
elements: blocks.map(b => b.element),
identifiers: blocks.map(b => b.element.getAttribute('identifier')),
data
}
)
const message = `\u2191 Updatable request affecting ${blocks.length} element(s): `

console.log(message, {
elements: blocks.map(b => b.element),
identifiers: blocks.map(b => b.element.getAttribute('identifier')),
data
})

return message
}

const cancel = (timestamp, reason) => {
if (Debug.disabled) return

const duration = new Date() - timestamp
console.log(
`\u274C Updatable request canceled after ${duration}ms: ${reason}`
)
const message = `\u274C Updatable request canceled after ${duration}ms: ${reason}`
console.log(message)

return message
}

const response = (timestamp, element, urls) => {
if (Debug.disabled) return

const duration = new Date() - timestamp
console.log(`\u2193 Updatable response: All URLs fetched in ${duration}ms`, {
const message = `\u2193 Updatable response: All URLs fetched in ${duration}ms`

console.log(message, {
element,
urls
})

return message
}

const morphStart = (timestamp, element) => {
if (Debug.disabled) return

const duration = new Date() - timestamp
console.log(`\u21BB Updatable morph: starting after ${duration}ms`, {
const message = `\u21BB Updatable morph: starting after ${duration}ms`

console.log(message, {
element
})

return message
}

const morphEnd = (timestamp, element) => {
if (Debug.disabled) return

const duration = new Date() - timestamp
console.log(`\u21BA Updatable morph: completed after ${duration}ms`, {
const message = `\u21BA Updatable morph: completed after ${duration}ms`

console.log(message, {
element
})

return message
}

export default { request, cancel, response, morphStart, morphEnd }
26 changes: 25 additions & 1 deletion javascript/utils.js
Expand Up @@ -205,6 +205,29 @@ async function graciouslyFetch (url, additionalHeaders) {
}
}

class BoundedQueue {
constructor (maxSize) {
this.maxSize = maxSize
this.queue = []
}

push (item) {
if (this.isFull()) {
// Remove the oldest item to make space for the new one
this.shift()
}
this.queue.push(item)
}

shift () {
return this.queue.shift()
}

isFull () {
return this.queue.length === this.maxSize
}
}

export {
isTextInput,
assignFocus,
Expand All @@ -225,5 +248,6 @@ export {
safeArray,
safeObject,
safeStringOrArray,
fragmentToString
fragmentToString,
BoundedQueue
}

0 comments on commit d4b8364

Please sign in to comment.