feat(network): use luna data grid
This commit is contained in:
@@ -13,7 +13,6 @@
|
||||
.title {
|
||||
position: relative;
|
||||
padding-bottom: 0;
|
||||
font-size: $font-size-l;
|
||||
color: var(--accent);
|
||||
.icon-copy {
|
||||
position: absolute;
|
||||
@@ -31,6 +30,7 @@
|
||||
margin: 0;
|
||||
user-select: text;
|
||||
color: var(--foreground);
|
||||
font-size: $font-size-s;
|
||||
word-break: break-all;
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import Tool from '../DevTools/Tool'
|
||||
import isEmpty from 'licia/isEmpty'
|
||||
import $ from 'licia/$'
|
||||
import ms from 'licia/ms'
|
||||
import each from 'licia/each'
|
||||
import last from 'licia/last'
|
||||
import Detail from './Detail'
|
||||
import map from 'licia/map'
|
||||
import escape from 'licia/escape'
|
||||
import throttle from 'licia/throttle'
|
||||
import { getFileName, classPrefix as c } from '../lib/util'
|
||||
import evalCss from '../lib/evalCss'
|
||||
import chobitsu from '../lib/chobitsu'
|
||||
import LunaDataGrid from 'luna-data-grid'
|
||||
import ResizeSensor from 'licia/ResizeSensor'
|
||||
|
||||
export default class Network extends Tool {
|
||||
constructor() {
|
||||
@@ -26,16 +26,53 @@ export default class Network extends Tool {
|
||||
this._container = container
|
||||
this._initTpl()
|
||||
this._detail = new Detail(this._$detail)
|
||||
this._requestDataGrid = new LunaDataGrid(this._$requests.get(0), {
|
||||
columns: [
|
||||
{
|
||||
id: 'name',
|
||||
title: 'Name',
|
||||
sortable: true,
|
||||
weight: 30,
|
||||
},
|
||||
{
|
||||
id: 'method',
|
||||
title: 'Method',
|
||||
sortable: true,
|
||||
weight: 14,
|
||||
},
|
||||
{
|
||||
id: 'status',
|
||||
title: 'Status',
|
||||
sortable: true,
|
||||
weight: 14,
|
||||
},
|
||||
{
|
||||
id: 'type',
|
||||
title: 'Type',
|
||||
sortable: true,
|
||||
weight: 14,
|
||||
},
|
||||
{
|
||||
id: 'size',
|
||||
title: 'Size',
|
||||
sortable: true,
|
||||
weight: 14,
|
||||
},
|
||||
{
|
||||
id: 'time',
|
||||
title: 'Time',
|
||||
sortable: true,
|
||||
weight: 14,
|
||||
},
|
||||
],
|
||||
})
|
||||
this._updateDataGridHeight()
|
||||
this._resizeSensor = new ResizeSensor($el.get(0))
|
||||
this._bindEvent()
|
||||
}
|
||||
show() {
|
||||
super.show()
|
||||
|
||||
this._render()
|
||||
}
|
||||
clear() {
|
||||
this._requests = {}
|
||||
this._render()
|
||||
this._requestDataGrid.clear()
|
||||
}
|
||||
requests() {
|
||||
const ret = []
|
||||
@@ -44,8 +81,13 @@ export default class Network extends Tool {
|
||||
})
|
||||
return ret
|
||||
}
|
||||
_updateDataGridHeight() {
|
||||
const height = this._$el.offset().height - 41
|
||||
this._requestDataGrid.setOption('minHeight', height)
|
||||
this._requestDataGrid.setOption('maxHeight', height)
|
||||
}
|
||||
_reqWillBeSent = (params) => {
|
||||
this._requests[params.requestId] = {
|
||||
const request = {
|
||||
name: getFileName(params.request.url),
|
||||
url: params.request.url,
|
||||
status: 'pending',
|
||||
@@ -61,60 +103,83 @@ export default class Network extends Tool {
|
||||
reqHeaders: params.request.headers || {},
|
||||
resHeaders: {},
|
||||
}
|
||||
let node
|
||||
request.render = () => {
|
||||
const data = {
|
||||
name: request.name,
|
||||
method: request.method,
|
||||
status: request.status,
|
||||
type: request.subType,
|
||||
size: request.size,
|
||||
time: request.displayTime,
|
||||
}
|
||||
if (node) {
|
||||
node.data = data
|
||||
node.render()
|
||||
} else {
|
||||
node = this._requestDataGrid.append(data, { selectable: true })
|
||||
$(node.container).data('id', params.requestId)
|
||||
}
|
||||
if (request.hasErr) {
|
||||
$(node.container).addClass(c('request-error'))
|
||||
}
|
||||
}
|
||||
request.render()
|
||||
this._requests[params.requestId] = request
|
||||
}
|
||||
_resReceivedExtraInfo = (params) => {
|
||||
const target = this._requests[params.requestId]
|
||||
if (!target) {
|
||||
const request = this._requests[params.requestId]
|
||||
if (!request) {
|
||||
return
|
||||
}
|
||||
|
||||
target.resHeaders = params.headers
|
||||
request.resHeaders = params.headers
|
||||
|
||||
this._updateType(target)
|
||||
this._render()
|
||||
this._updateType(request)
|
||||
request.render()
|
||||
}
|
||||
_updateType(target) {
|
||||
const contentType = target.resHeaders['content-type'] || ''
|
||||
_updateType(request) {
|
||||
const contentType = request.resHeaders['content-type'] || ''
|
||||
const { type, subType } = getType(contentType)
|
||||
target.type = type
|
||||
target.subType = subType
|
||||
request.type = type
|
||||
request.subType = subType
|
||||
}
|
||||
_resReceived = (params) => {
|
||||
const target = this._requests[params.requestId]
|
||||
if (!target) {
|
||||
const request = this._requests[params.requestId]
|
||||
if (!request) {
|
||||
return
|
||||
}
|
||||
|
||||
const { response } = params
|
||||
const { status, headers } = response
|
||||
target.status = status
|
||||
request.status = status
|
||||
if (status < 200 || status >= 300) {
|
||||
target.hasErr = true
|
||||
request.hasErr = true
|
||||
}
|
||||
if (headers) {
|
||||
target.resHeaders = headers
|
||||
this._updateType(target)
|
||||
request.resHeaders = headers
|
||||
this._updateType(request)
|
||||
}
|
||||
|
||||
this._render()
|
||||
request.render()
|
||||
}
|
||||
_loadingFinished = (params) => {
|
||||
const target = this._requests[params.requestId]
|
||||
if (!target) {
|
||||
const request = this._requests[params.requestId]
|
||||
if (!request) {
|
||||
return
|
||||
}
|
||||
|
||||
const time = params.timestamp * 1000
|
||||
target.time = time - target.startTime
|
||||
target.displayTime = ms(target.time)
|
||||
request.time = time - request.startTime
|
||||
request.displayTime = ms(request.time)
|
||||
|
||||
target.size = params.encodedDataLength
|
||||
target.done = true
|
||||
target.resTxt = chobitsu.domain('Network').getResponseBody({
|
||||
request.size = params.encodedDataLength
|
||||
request.done = true
|
||||
request.resTxt = chobitsu.domain('Network').getResponseBody({
|
||||
requestId: params.requestId,
|
||||
}).body
|
||||
|
||||
this._render()
|
||||
request.render()
|
||||
}
|
||||
_bindEvent() {
|
||||
const $el = this._$el
|
||||
@@ -122,16 +187,16 @@ export default class Network extends Tool {
|
||||
|
||||
const self = this
|
||||
|
||||
$el
|
||||
.on('click', c('.request'), function () {
|
||||
const id = $(this).data('id')
|
||||
const data = self._requests[id]
|
||||
$el.on('click', c('.clear-request'), () => this.clear())
|
||||
|
||||
if (!data.done) return
|
||||
|
||||
self._detail.show(data)
|
||||
})
|
||||
.on('click', c('.clear-request'), () => this.clear())
|
||||
this._requestDataGrid.on('select', (node) => {
|
||||
const id = $(node.container).data('id')
|
||||
const request = self._requests[id]
|
||||
if (!request.done) {
|
||||
return
|
||||
}
|
||||
self._detail.show(request)
|
||||
})
|
||||
|
||||
this._detail.on('showSources', function (type, data) {
|
||||
const sources = container.get('sources')
|
||||
@@ -142,6 +207,10 @@ export default class Network extends Tool {
|
||||
container.showTool('sources')
|
||||
})
|
||||
|
||||
this._resizeSensor.addListener(
|
||||
throttle(() => this._updateDataGridHeight(), 15)
|
||||
)
|
||||
|
||||
chobitsu.domain('Network').enable()
|
||||
|
||||
const network = chobitsu.domain('Network')
|
||||
@@ -153,6 +222,7 @@ export default class Network extends Tool {
|
||||
destroy() {
|
||||
super.destroy()
|
||||
|
||||
this._resizeSensor.destroy()
|
||||
evalCss.remove(this._style)
|
||||
|
||||
const network = chobitsu.domain('Network')
|
||||
@@ -170,45 +240,12 @@ export default class Network extends Tool {
|
||||
<span class="icon-clear"></span>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="requests"></ul>
|
||||
<div class="requests"></div>
|
||||
<div class="detail"></div>`)
|
||||
)
|
||||
this._$detail = $el.find(c('.detail'))
|
||||
this._$requests = $el.find(c('.requests'))
|
||||
}
|
||||
_render() {
|
||||
if (!this.active) return
|
||||
|
||||
const renderData = {}
|
||||
|
||||
if (!isEmpty(this._requests)) renderData.requests = this._requests
|
||||
|
||||
let html = `<li><span class="${c('name')}">Empty</span></li>`
|
||||
if (renderData.requests) {
|
||||
html = map(
|
||||
renderData.requests,
|
||||
({ hasErr, name, status, method, subType, size, displayTime }, idx) => {
|
||||
return `<li class="${c('request')} ${
|
||||
hasErr ? c('error') : ''
|
||||
}" data-id="${idx}">
|
||||
<span class="${c('name')}">${escape(name)}</span>
|
||||
<span class="${c('status')}">${status}</span>
|
||||
<span class="${c('method')}">${method}</span>
|
||||
<span class="${c('type')}">${subType}</span>
|
||||
<span class="${c('size')}">${size}</span>
|
||||
<span class="${c('time')}">${displayTime}</span>
|
||||
</li>`
|
||||
}
|
||||
).join('')
|
||||
}
|
||||
|
||||
this._renderHtml(html)
|
||||
}
|
||||
_renderHtml(html) {
|
||||
if (html === this._lastHtml) return
|
||||
this._lastHtml = html
|
||||
this._$requests.html(html)
|
||||
}
|
||||
}
|
||||
|
||||
function getType(contentType) {
|
||||
|
||||
@@ -2,65 +2,21 @@
|
||||
@import '../style/mixin';
|
||||
|
||||
#network {
|
||||
padding-top: 36px;
|
||||
padding-top: 40px;
|
||||
.title {
|
||||
@include absolute(100%, 36px);
|
||||
@include absolute(100%, 40px);
|
||||
@include right-btn();
|
||||
background: var(--darker-background);
|
||||
padding: $padding;
|
||||
color: var(--primary);
|
||||
height: 36px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
height: 40px;
|
||||
}
|
||||
.requests {
|
||||
@include overflow-auto(y);
|
||||
height: 100%;
|
||||
border-bottom: 1px solid var(--border);
|
||||
margin-bottom: 10px;
|
||||
li {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid var(--border);
|
||||
height: 41px;
|
||||
color: var(--foreground);
|
||||
white-space: nowrap;
|
||||
&.error {
|
||||
span {
|
||||
color: var(--console-error-foreground);
|
||||
}
|
||||
}
|
||||
span {
|
||||
display: block;
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
padding: 0 5px;
|
||||
font-size: $font-size-s;
|
||||
vertical-align: top;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
.name {
|
||||
flex: 1;
|
||||
padding-left: $padding;
|
||||
}
|
||||
.status {
|
||||
width: 40px;
|
||||
}
|
||||
.method,
|
||||
.type {
|
||||
width: 50px;
|
||||
}
|
||||
.size {
|
||||
width: 70px;
|
||||
}
|
||||
.time {
|
||||
width: 60px;
|
||||
padding-right: $padding;
|
||||
}
|
||||
&:nth-child(even) {
|
||||
background: var(--contrast);
|
||||
}
|
||||
.request-error {
|
||||
color: var(--console-error-foreground);
|
||||
}
|
||||
.luna-data-grid-data-container:focus {
|
||||
.request-error.luna-data-grid-selected {
|
||||
background: var(--console-error-background);
|
||||
}
|
||||
}
|
||||
.detail {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
padding: $padding;
|
||||
color: var(--primary);
|
||||
background: var(--darker-background);
|
||||
transition: background $anim-duration;
|
||||
transition: background-color $anim-duration;
|
||||
.btn {
|
||||
margin-left: 10px;
|
||||
float: right;
|
||||
@@ -31,6 +31,7 @@
|
||||
}
|
||||
}
|
||||
.description {
|
||||
font-size: $font-size-s;
|
||||
color: var(--foreground);
|
||||
padding: $padding;
|
||||
transition: background $anim-duration;
|
||||
|
||||
@@ -190,8 +190,6 @@ export function safeStorage(type, memReplacement) {
|
||||
export function getFileName(url) {
|
||||
let ret = last(url.split('/'))
|
||||
|
||||
if (ret.indexOf('?') > -1) ret = trim(ret.split('?')[0])
|
||||
|
||||
if (ret === '') {
|
||||
url = new Url(url)
|
||||
ret = url.hostname
|
||||
|
||||
@@ -181,6 +181,14 @@
|
||||
}
|
||||
}
|
||||
.luna-data-grid-data-container {
|
||||
&:focus {
|
||||
.luna-data-grid-node.luna-data-grid-selected {
|
||||
background: var(--accent);
|
||||
}
|
||||
}
|
||||
.luna-data-grid-node.luna-data-grid-selected {
|
||||
background: var(--highlight);
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background: var(--contrast);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: $font-size;
|
||||
[class^='icon-'],
|
||||
[class*=' icon-'] {
|
||||
font-weight: normal;
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('network', function () {
|
||||
it('xhr', function (done) {
|
||||
$('.eruda-clear-xhr').click()
|
||||
util.ajax.get(window.location.toString(), function () {
|
||||
expect($('.eruda-requests li')).toHaveLength(1)
|
||||
expect($('.eruda-requests .luna-data-grid-node')).toHaveLength(1)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user