Skip to content

Commit d826759

Browse files
author
Guillaume Chau
committed
Move data field edition to mixin + fixes
1 parent 75f98b9 commit d826759

File tree

4 files changed

+285
-207
lines changed

4 files changed

+285
-207
lines changed

src/devtools/components/DataField.vue

Lines changed: 26 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -148,24 +148,15 @@ import {
148148
INFINITY,
149149
NEGATIVE_INFINITY,
150150
NAN,
151-
SPECIAL_TOKENS,
152151
isPlainObject,
153-
sortByKey,
154-
parse
152+
sortByKey
155153
} from 'src/util'
156154
157-
const quickEditNumberTooltip = operator => `Quick Edit<br><br>
158-
<span class="keyboard">Ctrl</span> + <i class="material-icons">mouse</i>: ${operator}5<br>
159-
<span class="keyboard">Shift</span> + <i class="material-icons">mouse</i>: ${operator}10<br>
160-
<span class="keyboard">Alt</span> + <i class="material-icons">mouse</i>: ${operator}100`
161-
const QUICK_EDIT_NUMBER_REMOVE = quickEditNumberTooltip('-')
162-
const QUICK_EDIT_NUMBER_ADD = quickEditNumberTooltip('+')
155+
import DataFieldEdit from '../mixins/data-field-edit'
163156
164157
const rawTypeRE = /^\[object (\w+)]$/
165158
const specialTypeRE = /^\[native (\w+) (.*)\]$/
166159
167-
let currentEditedField = null
168-
169160
function subFieldCount (value) {
170161
if (Array.isArray(value)) {
171162
return value.length
@@ -176,63 +167,36 @@ function subFieldCount (value) {
176167
}
177168
}
178169
179-
function numberQuickEditMod (event) {
180-
let mod = 1
181-
if (event.ctrlKey) {
182-
mod *= 5
183-
}
184-
if (event.shiftKey) {
185-
mod *= 10
186-
}
187-
if (event.altKey) {
188-
mod *= 100
189-
}
190-
return mod
191-
}
192-
193170
export default {
194171
name: 'DataField',
172+
173+
mixins: [
174+
DataFieldEdit
175+
],
176+
195177
props: {
196178
field: Object,
197179
parentField: Object,
198180
depth: Number,
199-
path: String,
200-
editable: {
201-
type: Boolean,
202-
default: false
203-
},
204-
removable: {
205-
type: Boolean,
206-
default: false
207-
},
208-
renamable: {
209-
type: Boolean,
210-
default: false
211-
}
181+
path: String
212182
},
183+
213184
data () {
214185
return {
215186
limit: Array.isArray(this.field.value) ? 10 : Infinity,
216-
expanded: this.depth === 0 && this.field.key !== '$route' && (subFieldCount(this.field.value) < 5),
217-
editing: false,
218-
editedValue: null,
219-
editedKey: null,
220-
addingValue: false,
221-
newField: null
187+
expanded: this.depth === 0 && this.field.key !== '$route' && (subFieldCount(this.field.value) < 5)
222188
}
223189
},
190+
224191
computed: {
225192
...mapState('components', [
226193
'inspectedInstance'
227194
]),
228-
cssClass () {
229-
return {
230-
editing: this.editing
231-
}
232-
},
195+
233196
depthMargin () {
234197
return (this.depth + 1) * 14 + 10
235198
},
199+
236200
valueType () {
237201
const value = this.field.value
238202
const type = typeof value
@@ -261,9 +225,11 @@ export default {
261225
return 'unknown'
262226
}
263227
},
228+
264229
rawValueType () {
265230
return typeof this.field.value
266231
},
232+
267233
isExpandableType () {
268234
let value = this.field.value
269235
if (this.valueType === 'custom') {
@@ -281,29 +247,7 @@ export default {
281247
!closed
282248
)
283249
},
284-
isEditable () {
285-
return this.editable &&
286-
!this.fieldOptions.abstract &&
287-
!this.fieldOptions.readOnly &&
288-
(
289-
typeof this.field.key !== 'string' ||
290-
this.field.key.charAt(0) !== '$'
291-
)
292-
},
293-
isValueEditable () {
294-
const type = this.valueType
295-
return this.isEditable &&
296-
(
297-
type === 'null' ||
298-
type === 'literal' ||
299-
type === 'string' ||
300-
type === 'array' ||
301-
type === 'plain-object'
302-
)
303-
},
304-
isSubfieldsEditable () {
305-
return this.isEditable && (this.valueType === 'array' || this.valueType === 'plain-object')
306-
},
250+
307251
formattedValue () {
308252
const value = this.field.value
309253
if (this.fieldOptions.abstract) {
@@ -337,6 +281,7 @@ export default {
337281
return value
338282
}
339283
},
284+
340285
formattedSubFields () {
341286
let value = this.field.value
342287
@@ -363,33 +308,19 @@ export default {
363308
}
364309
return value
365310
},
311+
366312
limitedSubFields () {
367313
return this.formattedSubFields.slice(0, this.limit)
368314
},
315+
369316
fieldOptions () {
370317
if (this.valueType === 'custom') {
371318
return Object.assign({}, this.field, this.field.value._custom)
372319
} else {
373320
return this.field
374321
}
375322
},
376-
valueValid () {
377-
try {
378-
parse(this.transformSpecialTokens(this.editedValue, false))
379-
return true
380-
} catch (e) {
381-
return false
382-
}
383-
},
384-
duplicateKey () {
385-
return this.parentField.value.hasOwnProperty(this.editedKey)
386-
},
387-
keyValid () {
388-
return this.editedKey && (this.editedKey === this.field.key || !this.duplicateKey)
389-
},
390-
editValid () {
391-
return this.valueValid && (!this.renamable || this.keyValid)
392-
},
323+
393324
editErrorMessage () {
394325
if (!this.valueValid) {
395326
return 'Invalid value'
@@ -401,34 +332,7 @@ export default {
401332
}
402333
}
403334
},
404-
quickEdits () {
405-
if (this.isValueEditable) {
406-
const value = this.field.value
407-
const type = typeof value
408-
if (type === 'boolean') {
409-
return [
410-
{
411-
icon: value ? 'check_box' : 'check_box_outline_blank',
412-
newValue: !value
413-
}
414-
]
415-
} else if (type === 'number') {
416-
return [
417-
{
418-
icon: 'remove',
419-
title: QUICK_EDIT_NUMBER_REMOVE,
420-
newValue: event => value - numberQuickEditMod(event)
421-
},
422-
{
423-
icon: 'add',
424-
title: QUICK_EDIT_NUMBER_ADD,
425-
newValue: event => value + numberQuickEditMod(event)
426-
}
427-
]
428-
}
429-
}
430-
return null
431-
},
335+
432336
valueClass () {
433337
const cssClass = [this.valueType, `raw-${this.rawValueType}`]
434338
if (this.valueType === 'custom') {
@@ -437,103 +341,22 @@ export default {
437341
value._custom.class && cssClass.push(value._custom.class)
438342
}
439343
return cssClass
440-
},
441-
cancelEditTooltip () {
442-
return '<span class="keyboard">Esc</span> Cancel'
443-
},
444-
submitEditTooltip () {
445-
return '<span class="keyboard">Enter</span> Submit change'
446344
}
447345
},
346+
448347
methods: {
449348
toggle (event) {
450349
if (event.target.tagName === 'INPUT' || event.target.className.includes('button')) {
451350
return
452351
}
453352
if (this.isExpandableType) {
454353
this.expanded = !this.expanded
354+
355+
!this.expanded && this.cancelCurrentEdition()
455356
}
456357
},
457-
hyphen: v => v.replace(/\s/g, '-'),
458-
openEdit (focusKey = false) {
459-
if (this.isValueEditable) {
460-
if (currentEditedField && currentEditedField !== this) {
461-
currentEditedField.cancelEdit()
462-
}
463-
this.editedValue = this.transformSpecialTokens(JSON.stringify(this.field.value), true)
464-
this.editedKey = this.field.key
465-
this.editing = true
466-
currentEditedField = this
467-
this.$nextTick(() => {
468-
const el = this.$refs[focusKey && this.renamable ? 'keyInput' : 'editInput']
469-
el.focus()
470-
el.setSelectionRange(0, el.value.length)
471-
})
472-
}
473-
},
474-
cancelEdit () {
475-
this.editing = false
476-
this.$emit('cancel-edit')
477-
},
478-
submitEdit () {
479-
if (this.editValid) {
480-
this.editing = false
481-
const value = this.transformSpecialTokens(this.editedValue, false)
482-
const newKey = this.editedKey !== this.field.key ? this.editedKey : undefined
483-
this.sendEdit({ value, newKey })
484-
this.$emit('submit-edit')
485-
}
486-
},
487-
sendEdit (args) {
488-
bridge.send('set-instance-data', {
489-
id: this.inspectedInstance.id,
490-
path: this.path,
491-
...args
492-
})
493-
},
494-
transformSpecialTokens (str, display) {
495-
Object.keys(SPECIAL_TOKENS).forEach(key => {
496-
const value = JSON.stringify(SPECIAL_TOKENS[key])
497-
let search
498-
let replace
499-
if (display) {
500-
search = value
501-
replace = key
502-
} else {
503-
search = key
504-
replace = value
505-
}
506-
str = str.replace(new RegExp(search), replace)
507-
})
508-
return str
509-
},
510-
quickEdit (info, event) {
511-
let newValue
512-
if (typeof info.newValue === 'function') {
513-
newValue = info.newValue(event)
514-
} else {
515-
newValue = info.newValue
516-
}
517-
this.sendEdit({ value: JSON.stringify(newValue) })
518-
},
519-
removeField () {
520-
this.sendEdit({ remove: true })
521-
},
522-
addNewValue () {
523-
let key
524-
if (this.valueType === 'array') {
525-
key = this.field.value.length
526-
} else if (this.valueType === 'plain-object') {
527-
let i = 1
528-
while (this.field.value.hasOwnProperty(key = `prop${i}`)) i++
529-
}
530-
this.newField = { key, value: UNDEFINED }
531-
this.expanded = true
532-
this.addingValue = true
533-
this.$nextTick(() => {
534-
this.$refs.newField.openEdit(true)
535-
})
536-
}
358+
359+
hyphen: v => v.replace(/\s/g, '-')
537360
}
538361
}
539362
</script>

src/devtools/components/StateInspector.vue

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ export default {
7878
})
7979
},
8080
dataTypeTooltip () {
81-
const ctrlKey = navigator.platform === 'MacIntel' ? '&#8984;' : 'Ctrl'
82-
return `<span class="keyboard">${ctrlKey}</span> + <i class="material-icons">mouse</i>: Collapse All<br><span class="keyboard">Shift</span> + <i class="material-icons">mouse</i>: Expand All`
81+
return `<span class="keyboard">${this.$keys.ctrl}</span> + <i class="material-icons">mouse</i>: Collapse All<br><span class="keyboard">Shift</span> + <i class="material-icons">mouse</i>: Expand All`
8382
}
8483
},
8584
methods: {

src/devtools/index.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,22 @@ import store from './store'
44
import './plugins'
55
import { parse } from '../util'
66

7+
// Env
8+
79
const isChrome = typeof chrome !== 'undefined' && !!chrome.devtools
8-
Object.defineProperty(Vue.prototype, '$isChrome', {
9-
get () { return isChrome }
10+
const isMac = navigator.platform === 'MacIntel'
11+
const keys = {
12+
ctrl: isMac ? '&#8984;' : 'Ctrl'
13+
}
14+
15+
Object.defineProperties(Vue.prototype, {
16+
'$isChrome': { get: () => isChrome },
17+
'$isMac': { get: () => isMac },
18+
'$keys': { get: () => keys }
1019
})
1120

21+
// UI
22+
1223
let panelShown = !isChrome
1324
let pendingAction = null
1425

0 commit comments

Comments
 (0)