feat(resources): use luna data grid
This commit is contained in:
@@ -201,7 +201,6 @@ export default class DevTools extends Emitter {
|
||||
const store = safeStorage('local')
|
||||
|
||||
const data = JSON.parse(JSON.stringify(store))
|
||||
console.log(data)
|
||||
each(data, (val, key) => {
|
||||
if (!isStr(val)) {
|
||||
return
|
||||
|
||||
@@ -46,9 +46,9 @@ export default [
|
||||
{
|
||||
name: 'Backers',
|
||||
val() {
|
||||
return `<a rel="noreferrer noopener" href="https://opencollective.com/eruda" target="_blank"><img style="width: 100%;"src="https://opencollective.com/eruda/backers.svg?width=${
|
||||
return `<a rel="noreferrer noopener" href="https://opencollective.com/eruda" target="_blank"><img data-exclude="true" style="width: 100%;"src="https://opencollective.com/eruda/backers.svg?width=${
|
||||
window.innerWidth * 1.5
|
||||
}"></a>`
|
||||
}&exclude=true"></a>`
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import map from 'licia/map'
|
||||
import isEmpty from 'licia/isEmpty'
|
||||
import $ from 'licia/$'
|
||||
import trim from 'licia/trim'
|
||||
import isNull from 'licia/isNull'
|
||||
import escape from 'licia/escape'
|
||||
import each from 'licia/each'
|
||||
import LunaModal from 'luna-modal'
|
||||
import { setState, getState, filterData } from './util'
|
||||
import LunaDataGrid from 'luna-data-grid'
|
||||
import { setState, getState } from './util'
|
||||
import chobitsu from '../lib/chobitsu'
|
||||
import { classPrefix as c } from '../lib/util'
|
||||
|
||||
@@ -13,70 +12,110 @@ export default class Cookie {
|
||||
constructor($container, devtools) {
|
||||
this._$container = $container
|
||||
this._devtools = devtools
|
||||
this._filter = ''
|
||||
this._selectedItem = null
|
||||
|
||||
this._initTpl()
|
||||
this._dataGrid = new LunaDataGrid(this._$dataGrid.get(0), {
|
||||
columns: [
|
||||
{
|
||||
id: 'key',
|
||||
title: 'Key',
|
||||
weight: 30,
|
||||
},
|
||||
{
|
||||
id: 'value',
|
||||
title: 'Value',
|
||||
weight: 90,
|
||||
},
|
||||
],
|
||||
minHeight: 60,
|
||||
maxHeight: 223,
|
||||
})
|
||||
|
||||
this._bindEvent()
|
||||
}
|
||||
refresh() {
|
||||
const $container = this._$container
|
||||
const filter = this._filter
|
||||
const dataGrid = this._dataGrid
|
||||
|
||||
const { cookies } = chobitsu.domain('Network').getCookies()
|
||||
let cookieData = map(cookies, ({ name, value }) => ({
|
||||
const cookieData = map(cookies, ({ name, value }) => ({
|
||||
key: name,
|
||||
val: value,
|
||||
}))
|
||||
|
||||
cookieData = filterData(cookieData, filter)
|
||||
dataGrid.clear()
|
||||
each(cookieData, ({ key, val }) => {
|
||||
dataGrid.append(
|
||||
{
|
||||
key,
|
||||
value: val,
|
||||
},
|
||||
{
|
||||
selectable: true,
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
const cookieState = getState('cookie', cookieData.length)
|
||||
setState($container, cookieState)
|
||||
}
|
||||
_initTpl() {
|
||||
const $container = this._$container
|
||||
|
||||
let cookieDataHtml = '<tr><td>Empty</td></tr>'
|
||||
if (!isEmpty(cookieData)) {
|
||||
cookieDataHtml = map(cookieData, ({ key, val }) => {
|
||||
key = escape(key)
|
||||
$container.html(
|
||||
c(`<h2 class="title">
|
||||
Cookie
|
||||
<div class="btn refresh-cookie">
|
||||
<span class="icon-refresh"></span>
|
||||
</div>
|
||||
<div class="btn show-detail btn-disabled">
|
||||
<span class="icon icon-eye"></span>
|
||||
</div>
|
||||
<div class="btn delete-cookie btn-disabled">
|
||||
<span class="icon icon-delete"></span>
|
||||
</div>
|
||||
<div class="btn clear-cookie">
|
||||
<span class="icon-clear"></span>
|
||||
</div>
|
||||
<div class="btn filter" data-type="cookie">
|
||||
<span class="icon-filter"></span>
|
||||
</div>
|
||||
<div class="btn filter-text"></div>
|
||||
</h2>
|
||||
<div class="data-grid"></div>`)
|
||||
)
|
||||
|
||||
return `<tr>
|
||||
<td class="${c('key')}">${key}</td>
|
||||
<td>${escape(val)}</td>
|
||||
<td class="${c('control')}">
|
||||
<span class="${c(
|
||||
'icon-delete delete-cookie'
|
||||
)}" data-key="${key}"></span>
|
||||
</td>
|
||||
</tr>`
|
||||
}).join('')
|
||||
this._$dataGrid = $container.find(c('.data-grid'))
|
||||
this._$filterText = $container.find(c('.filter-text'))
|
||||
}
|
||||
_updateButtons() {
|
||||
const $container = this._$container
|
||||
const $showDetail = $container.find(c('.show-detail'))
|
||||
const $deleteCookie = $container.find(c('.delete-cookie'))
|
||||
const btnDisabled = c('btn-disabled')
|
||||
|
||||
$showDetail.addClass(btnDisabled)
|
||||
$deleteCookie.addClass(btnDisabled)
|
||||
|
||||
if (this._selectedItem) {
|
||||
$showDetail.rmClass(btnDisabled)
|
||||
$deleteCookie.rmClass(btnDisabled)
|
||||
}
|
||||
}
|
||||
_getVal(key) {
|
||||
const { cookies } = chobitsu.domain('Network').getCookies()
|
||||
|
||||
for (let i = 0, len = cookies.length; i < len; i++) {
|
||||
if (cookies[i].name === key) {
|
||||
return cookies[i].value
|
||||
}
|
||||
}
|
||||
|
||||
setState($container, cookieState)
|
||||
|
||||
$container.html(`<h2 class="${c('title')}">
|
||||
Cookie
|
||||
<div class="${c('btn refresh-cookie')}">
|
||||
<span class="${c('icon-refresh')}"></span>
|
||||
</div>
|
||||
<div class="${c('btn clear-cookie')}">
|
||||
<span class="${c('icon-clear')}"></span>
|
||||
</div>
|
||||
<div class="${c('btn filter')}" data-type="cookie">
|
||||
<span class="${c('icon-filter')}"></span>
|
||||
</div>
|
||||
${
|
||||
filter
|
||||
? `<div class="${c('btn filter-text')}">${escape(filter)}</div>`
|
||||
: ''
|
||||
}
|
||||
</h2>
|
||||
<div class="${c('content')}">
|
||||
<table>
|
||||
<tbody>
|
||||
${cookieDataHtml}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>`)
|
||||
return ''
|
||||
}
|
||||
_bindEvent() {
|
||||
const devtools = this._devtools
|
||||
const self = this
|
||||
|
||||
this._$container
|
||||
.on('click', c('.refresh-cookie'), () => {
|
||||
@@ -89,19 +128,51 @@ export default class Cookie {
|
||||
})
|
||||
this.refresh()
|
||||
})
|
||||
.on('click', c('.delete-cookie'), function () {
|
||||
const key = $(this).data('key')
|
||||
.on('click', c('.delete-cookie'), () => {
|
||||
const key = this._selectedItem
|
||||
|
||||
chobitsu.domain('Network').deleteCookies({ name: key })
|
||||
self.refresh()
|
||||
this.refresh()
|
||||
})
|
||||
.on('click', c('.show-detail'), () => {
|
||||
const key = this._selectedItem
|
||||
const val = this._getVal(key)
|
||||
|
||||
try {
|
||||
showSources('object', JSON.parse(val))
|
||||
} catch (e) {
|
||||
showSources('raw', val)
|
||||
}
|
||||
})
|
||||
.on('click', c('.filter'), () => {
|
||||
LunaModal.prompt('Filter').then((filter) => {
|
||||
if (isNull(filter)) return
|
||||
filter = trim(filter)
|
||||
this._filter = filter
|
||||
this.refresh()
|
||||
this._$filterText.text(filter)
|
||||
this._dataGrid.setOption('filter', filter)
|
||||
})
|
||||
})
|
||||
|
||||
function showSources(type, data) {
|
||||
const sources = devtools.get('sources')
|
||||
if (!sources) return
|
||||
|
||||
sources.set(type, data)
|
||||
|
||||
devtools.showTool('sources')
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
this._dataGrid
|
||||
.on('select', (node) => {
|
||||
this._selectedItem = node.data.key
|
||||
this._updateButtons()
|
||||
})
|
||||
.on('deselect', () => {
|
||||
this._selectedItem = null
|
||||
this._updateButtons()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import Settings from '../Settings/Settings'
|
||||
import $ from 'licia/$'
|
||||
import escape from 'licia/escape'
|
||||
import isEmpty from 'licia/isEmpty'
|
||||
import contain from 'licia/contain'
|
||||
import unique from 'licia/unique'
|
||||
import each from 'licia/each'
|
||||
import sameOrigin from 'licia/sameOrigin'
|
||||
@@ -202,6 +203,9 @@ export default class Resources extends Tool {
|
||||
const entries = this._performance.getEntries()
|
||||
entries.forEach((entry) => {
|
||||
if (entry.initiatorType === 'img' || isImg(entry.name)) {
|
||||
if (contain(entry.name, 'exclude=true')) {
|
||||
return
|
||||
}
|
||||
imageData.push(entry.name)
|
||||
}
|
||||
})
|
||||
@@ -210,7 +214,9 @@ export default class Resources extends Tool {
|
||||
const $this = $(this)
|
||||
const src = $this.attr('src')
|
||||
|
||||
if ($this.data('exclude') === 'true') return
|
||||
if ($this.data('exclude') === 'true') {
|
||||
return
|
||||
}
|
||||
|
||||
imageData.push(src)
|
||||
})
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
.content {
|
||||
@include overflow-auto(y);
|
||||
max-height: 400px;
|
||||
}
|
||||
&.warn {
|
||||
border: 1px solid var(--console-warn-border);
|
||||
.title {
|
||||
@@ -27,6 +23,15 @@
|
||||
color: var(--console-error-foreground);
|
||||
}
|
||||
}
|
||||
&.local-storage,
|
||||
&.session-storage,
|
||||
&.cookie {
|
||||
border: none;
|
||||
.title {
|
||||
border: 1px solid var(--border);
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title {
|
||||
@include right-btn();
|
||||
@@ -68,41 +73,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
table {
|
||||
color: var(--foreground);
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
font-size: $font-size-s;
|
||||
tr:nth-child(even) {
|
||||
background: var(--contrast);
|
||||
}
|
||||
td {
|
||||
padding: 10px;
|
||||
word-break: break-all;
|
||||
&.key {
|
||||
@include overflow-auto(x);
|
||||
white-space: nowrap;
|
||||
max-width: 120px;
|
||||
}
|
||||
&.control {
|
||||
padding: 0;
|
||||
font-size: 0;
|
||||
width: 40px;
|
||||
.icon-delete {
|
||||
cursor: pointer;
|
||||
color: var(--primary);
|
||||
font-size: $font-size;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
transition: color $anim-duration;
|
||||
&:active {
|
||||
color: var(--accent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
import isEmpty from 'licia/isEmpty'
|
||||
import map from 'licia/map'
|
||||
import each from 'licia/each'
|
||||
import isStr from 'licia/isStr'
|
||||
import startWith from 'licia/startWith'
|
||||
import truncate from 'licia/truncate'
|
||||
import escape from 'licia/escape'
|
||||
import $ from 'licia/$'
|
||||
import LunaModal from 'luna-modal'
|
||||
import LunaDataGrid from 'luna-data-grid'
|
||||
import isNull from 'licia/isNull'
|
||||
import trim from 'licia/trim'
|
||||
import { safeStorage, classPrefix as c } from '../lib/util'
|
||||
import { filterData } from './util'
|
||||
|
||||
export default class Storage {
|
||||
constructor($container, devtools, resources, type) {
|
||||
@@ -18,58 +14,46 @@ export default class Storage {
|
||||
this._$container = $container
|
||||
this._devtools = devtools
|
||||
this._resources = resources
|
||||
this._filter = ''
|
||||
this._selectedItem = null
|
||||
this._storeData = []
|
||||
|
||||
this._initTpl()
|
||||
this._dataGrid = new LunaDataGrid(this._$dataGrid.get(0), {
|
||||
columns: [
|
||||
{
|
||||
id: 'key',
|
||||
title: 'Key',
|
||||
weight: 30,
|
||||
},
|
||||
{
|
||||
id: 'value',
|
||||
title: 'Value',
|
||||
weight: 90,
|
||||
},
|
||||
],
|
||||
minHeight: 60,
|
||||
maxHeight: 223,
|
||||
})
|
||||
|
||||
this._bindEvent()
|
||||
}
|
||||
refresh() {
|
||||
const filter = this._filter
|
||||
const dataGrid = this._dataGrid
|
||||
|
||||
this._refreshStorage()
|
||||
dataGrid.clear()
|
||||
|
||||
const storeData = filterData(this._storeData, filter)
|
||||
let storeDataHtml = '<tr><td>Empty</td></tr>'
|
||||
if (!isEmpty(storeData)) {
|
||||
storeDataHtml = map(storeData, ({ key, val }) => {
|
||||
key = escape(key)
|
||||
|
||||
return `<tr>
|
||||
<td class="${c('key')}">${key}</td>
|
||||
<td class="${c('storage-val')}" data-key="${key}">${escape(val)}</td>
|
||||
<td class="${c('control')}">
|
||||
<span class="${c(
|
||||
'icon-delete delete-storage'
|
||||
)}" data-key="${key}"></span>
|
||||
</td>
|
||||
</tr>`
|
||||
}).join('')
|
||||
}
|
||||
|
||||
this._$container.html(`<h2 class="${c('title')}">
|
||||
Local Storage
|
||||
<div class="${c('btn refresh-storage')}">
|
||||
<span class="${c('icon-refresh')}"></span>
|
||||
</div>
|
||||
<div class="${c('btn clear-storage')}">
|
||||
<span class="${c('icon-clear')}"></span>
|
||||
</div>
|
||||
<div class="${c('btn filter')}">
|
||||
<span class="${c('icon-filter')}"></span>
|
||||
</div>
|
||||
${
|
||||
filter
|
||||
? `<div class="${c('btn filter-text')}">${escape(filter)}</div>`
|
||||
: ''
|
||||
}
|
||||
</h2>
|
||||
<div class="${c('content')}">
|
||||
<table>
|
||||
<tbody>
|
||||
${storeDataHtml}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>`)
|
||||
each(this._storeData, ({ key, val }) => {
|
||||
dataGrid.append(
|
||||
{
|
||||
key,
|
||||
value: val,
|
||||
},
|
||||
{
|
||||
selectable: true,
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
_refreshStorage() {
|
||||
const resources = this._resources
|
||||
@@ -99,29 +83,71 @@ export default class Storage {
|
||||
|
||||
this._storeData = storeData
|
||||
}
|
||||
_updateButtons() {
|
||||
const $container = this._$container
|
||||
const $showDetail = $container.find(c('.show-detail'))
|
||||
const $deleteStorage = $container.find(c('.delete-storage'))
|
||||
const btnDisabled = c('btn-disabled')
|
||||
|
||||
$showDetail.addClass(btnDisabled)
|
||||
$deleteStorage.addClass(btnDisabled)
|
||||
|
||||
if (this._selectedItem) {
|
||||
$showDetail.rmClass(btnDisabled)
|
||||
$deleteStorage.rmClass(btnDisabled)
|
||||
}
|
||||
}
|
||||
_initTpl() {
|
||||
const $container = this._$container
|
||||
const type = this._type
|
||||
|
||||
$container.html(
|
||||
c(`<h2 class="title">
|
||||
${type === 'local' ? 'Local' : 'Session'} Storage
|
||||
<div class="btn refresh-storage">
|
||||
<span class="icon icon-refresh"></span>
|
||||
</div>
|
||||
<div class="btn show-detail btn-disabled">
|
||||
<span class="icon icon-eye"></span>
|
||||
</div>
|
||||
<div class="btn delete-storage btn-disabled">
|
||||
<span class="icon icon-delete"></span>
|
||||
</div>
|
||||
<div class="btn clear-storage">
|
||||
<span class="icon icon-clear"></span>
|
||||
</div>
|
||||
<div class="btn filter">
|
||||
<span class="icon icon-filter"></span>
|
||||
</div>
|
||||
<div class="btn filter-text"></div>
|
||||
</h2>
|
||||
<div class="data-grid"></div>`)
|
||||
)
|
||||
|
||||
this._$dataGrid = $container.find(c('.data-grid'))
|
||||
this._$filterText = $container.find(c('.filter-text'))
|
||||
}
|
||||
_bindEvent() {
|
||||
const type = this._type
|
||||
const devtools = this._devtools
|
||||
const self = this
|
||||
|
||||
this._$container
|
||||
.on('click', c('.refresh-storage'), () => {
|
||||
devtools.notify('Refreshed')
|
||||
this.refresh()
|
||||
})
|
||||
.on('click', c('.clear-storage'), function () {
|
||||
each(self._storeData, (val) => {
|
||||
.on('click', c('.clear-storage'), () => {
|
||||
each(this._storeData, (val) => {
|
||||
if (type === 'local') {
|
||||
localStorage.removeItem(val.key)
|
||||
} else {
|
||||
sessionStorage.removeItem(val.key)
|
||||
}
|
||||
})
|
||||
self.refresh()
|
||||
this.refresh()
|
||||
})
|
||||
.on('click', c('.storage-val'), function () {
|
||||
const $this = $(this)
|
||||
const key = $this.data('key')
|
||||
.on('click', c('.show-detail'), () => {
|
||||
const key = this._selectedItem
|
||||
|
||||
const val =
|
||||
type === 'local'
|
||||
@@ -138,13 +164,12 @@ export default class Storage {
|
||||
LunaModal.prompt('Filter').then((filter) => {
|
||||
if (isNull(filter)) return
|
||||
filter = trim(filter)
|
||||
this._filter = filter
|
||||
this.refresh()
|
||||
this._$filterText.text(filter)
|
||||
this._dataGrid.setOption('filter', filter)
|
||||
})
|
||||
})
|
||||
.on('click', c('.delete-storage'), function () {
|
||||
const $this = $(this)
|
||||
const key = $this.data('key')
|
||||
.on('click', c('.delete-storage'), () => {
|
||||
const key = this._selectedItem
|
||||
|
||||
if (type === 'local') {
|
||||
localStorage.removeItem(key)
|
||||
@@ -152,7 +177,7 @@ export default class Storage {
|
||||
sessionStorage.removeItem(key)
|
||||
}
|
||||
|
||||
self.refresh()
|
||||
this.refresh()
|
||||
})
|
||||
|
||||
function showSources(type, data) {
|
||||
@@ -165,5 +190,15 @@ export default class Storage {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
this._dataGrid
|
||||
.on('select', (node) => {
|
||||
this._selectedItem = node.data.key
|
||||
this._updateButtons()
|
||||
})
|
||||
.on('deselect', () => {
|
||||
this._selectedItem = null
|
||||
this._updateButtons()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,5 @@
|
||||
import lowerCase from 'licia/lowerCase'
|
||||
import contain from 'licia/contain'
|
||||
import filter from 'licia/filter'
|
||||
import { classPrefix as c } from '../lib/util'
|
||||
|
||||
export function filterData(data, keyword) {
|
||||
keyword = lowerCase(keyword)
|
||||
|
||||
if (!keyword) return data
|
||||
|
||||
return filter(data, ({ key, val }) => {
|
||||
return contain(lowerCase(key), keyword) || contain(lowerCase(val), keyword)
|
||||
})
|
||||
}
|
||||
|
||||
export function setState($el, state) {
|
||||
$el
|
||||
.rmClass(c('ok'))
|
||||
|
||||
@@ -83,5 +83,11 @@
|
||||
&:active {
|
||||
color: var(--accent);
|
||||
}
|
||||
&.btn-disabled {
|
||||
color: inherit !important;
|
||||
cursor: default !important;
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user