mockaton 10.6.1 → 10.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/Dashboard.js +146 -116
- package/src/DashboardHtml.js +11 -11
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "mockaton",
|
|
3
3
|
"description": "HTTP Mock Server",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "10.6.
|
|
5
|
+
"version": "10.6.3",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
8
|
"license": "MIT",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"start": "node src/cli.js",
|
|
24
24
|
"watch": "node --watch src/cli.js",
|
|
25
25
|
"pixaton": "node --test --import=./pixaton-tests/_setup.js --experimental-test-isolation=none 'pixaton-tests/**/*.test.js'",
|
|
26
|
-
"outdated": "npm outdated --parseable | awk -F: '{ printf \"npm i
|
|
26
|
+
"outdated": "npm outdated --parseable | awk -F: '{ printf \"npm i %s ;# %s\\n\", $4, $2 }'"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"pixaton": "1.1.3",
|
package/src/Dashboard.js
CHANGED
|
@@ -69,6 +69,12 @@ const state = /** @type {State} */ {
|
|
|
69
69
|
return Boolean(state.proxyFallback)
|
|
70
70
|
},
|
|
71
71
|
|
|
72
|
+
fileFor(method, urlMask) {
|
|
73
|
+
return state.brokersByMethod[method]?.[urlMask]?.currentMock.file
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
leftSideWidth: window.innerWidth / 2,
|
|
77
|
+
|
|
72
78
|
groupByMethod: initPreference('groupByMethod'),
|
|
73
79
|
toggleGroupByMethod() {
|
|
74
80
|
state.groupByMethod = !state.groupByMethod
|
|
@@ -76,10 +82,7 @@ const state = /** @type {State} */ {
|
|
|
76
82
|
updateState()
|
|
77
83
|
},
|
|
78
84
|
|
|
79
|
-
leftSideWidth: window.innerWidth / 2,
|
|
80
|
-
|
|
81
85
|
chosenLink: { method: '', urlMask: '' },
|
|
82
|
-
clearChosenLink() { state.setChosenLink('', '') },
|
|
83
86
|
setChosenLink(method, urlMask) {
|
|
84
87
|
state.chosenLink = { method, urlMask }
|
|
85
88
|
}
|
|
@@ -88,7 +91,7 @@ const state = /** @type {State} */ {
|
|
|
88
91
|
|
|
89
92
|
const mockaton = new Commander(location.origin)
|
|
90
93
|
updateState()
|
|
91
|
-
|
|
94
|
+
initRealTimeUpdates()
|
|
92
95
|
initKeyboardNavigation()
|
|
93
96
|
|
|
94
97
|
async function updateState() {
|
|
@@ -96,13 +99,18 @@ async function updateState() {
|
|
|
96
99
|
const response = await mockaton.getState()
|
|
97
100
|
if (!response.ok)
|
|
98
101
|
throw response.status
|
|
102
|
+
|
|
99
103
|
Object.assign(state, await response.json())
|
|
104
|
+
|
|
105
|
+
const focusedElem = selectorFor(document.activeElement)
|
|
100
106
|
document.body.replaceChildren(...App())
|
|
107
|
+
if (focusedElem)
|
|
108
|
+
document.querySelector(focusedElem)?.focus()
|
|
101
109
|
|
|
102
|
-
findChosenLink()?.focus()
|
|
103
110
|
const { method, urlMask } = state.chosenLink
|
|
104
111
|
if (method && urlMask)
|
|
105
112
|
await previewMock(method, urlMask)
|
|
113
|
+
|
|
106
114
|
}
|
|
107
115
|
catch (error) {
|
|
108
116
|
onError(error)
|
|
@@ -167,7 +175,7 @@ function SettingsMenuTrigger() {
|
|
|
167
175
|
|
|
168
176
|
function SettingsMenu(id) {
|
|
169
177
|
const { groupByMethod, toggleGroupByMethod } = state
|
|
170
|
-
|
|
178
|
+
|
|
171
179
|
const firstInputRef = useRef()
|
|
172
180
|
function onToggle(event) {
|
|
173
181
|
if (event.newState === 'open')
|
|
@@ -225,13 +233,11 @@ function BulkSelector() {
|
|
|
225
233
|
// But this way is easier to implement, with a few hacks.
|
|
226
234
|
const firstOption = t`Pick Comment…`
|
|
227
235
|
function onChange() {
|
|
228
|
-
state.clearChosenLink()
|
|
229
236
|
const value = this.value
|
|
230
237
|
this.value = firstOption // Hack
|
|
231
238
|
mockaton.bulkSelectByComment(value)
|
|
232
239
|
.then(parseError)
|
|
233
240
|
.then(updateState)
|
|
234
|
-
.then(() => focus(`.${CSS.BulkSelector}`))
|
|
235
241
|
.catch(onError)
|
|
236
242
|
}
|
|
237
243
|
const disabled = !comments.length
|
|
@@ -296,7 +302,6 @@ function ProxyFallbackField() {
|
|
|
296
302
|
mockaton.setProxyFallback(this.value.trim())
|
|
297
303
|
.then(parseError)
|
|
298
304
|
.then(updateState)
|
|
299
|
-
.then(() => focus(`.${CSS.FallbackBackend} input`))
|
|
300
305
|
.catch(onError)
|
|
301
306
|
}
|
|
302
307
|
return (
|
|
@@ -334,11 +339,10 @@ function SaveProxiedCheckbox(ref) {
|
|
|
334
339
|
|
|
335
340
|
function ResetButton() {
|
|
336
341
|
function onClick() {
|
|
337
|
-
state.
|
|
342
|
+
state.setChosenLink('', '')
|
|
338
343
|
mockaton.reset()
|
|
339
344
|
.then(parseError)
|
|
340
345
|
.then(updateState)
|
|
341
|
-
.then(() => focus(`.${CSS.ResetButton}`))
|
|
342
346
|
.catch(onError)
|
|
343
347
|
}
|
|
344
348
|
return (
|
|
@@ -374,7 +378,7 @@ function MockList() {
|
|
|
374
378
|
function Row({ method, urlMask, urlMaskDittoed, broker }, i) {
|
|
375
379
|
const { canProxy, groupByMethod } = state
|
|
376
380
|
return (
|
|
377
|
-
r('tr', {
|
|
381
|
+
r('tr', { key: method + '::' + urlMask },
|
|
378
382
|
canProxy && r('td', null, ProxyToggler(broker)),
|
|
379
383
|
r('td', null, DelayRouteToggler(broker)),
|
|
380
384
|
r('td', null, InternalServerErrorToggler(broker)),
|
|
@@ -627,6 +631,7 @@ function ClickDragToggler({ checked, commit, focusGroup }) {
|
|
|
627
631
|
}
|
|
628
632
|
function onPointerDown() {
|
|
629
633
|
this.checked = !this.checked
|
|
634
|
+
this.focus()
|
|
630
635
|
commit(this.checked)
|
|
631
636
|
}
|
|
632
637
|
function onClick(event) {
|
|
@@ -655,68 +660,69 @@ function ClickDragToggler({ checked, commit, focusGroup }) {
|
|
|
655
660
|
|
|
656
661
|
|
|
657
662
|
function Resizer() {
|
|
663
|
+
let raf = 0
|
|
664
|
+
let initialX = 0
|
|
665
|
+
let panelWidth = 0
|
|
666
|
+
|
|
667
|
+
function onPointerDown(event) {
|
|
668
|
+
initialX = event.clientX
|
|
669
|
+
panelWidth = leftSideRef.current.clientWidth
|
|
670
|
+
addEventListener('pointerup', onUp, { once: true })
|
|
671
|
+
addEventListener('pointermove', onMove)
|
|
672
|
+
Object.assign(document.body.style, {
|
|
673
|
+
cursor: 'col-resize',
|
|
674
|
+
userSelect: 'none',
|
|
675
|
+
pointerEvents: 'none'
|
|
676
|
+
})
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function onMove(event) {
|
|
680
|
+
const MIN_LEFT_WIDTH = 380
|
|
681
|
+
raf = raf || requestAnimationFrame(() => {
|
|
682
|
+
state.leftSideWidth = Math.max(panelWidth - (initialX - event.clientX), MIN_LEFT_WIDTH)
|
|
683
|
+
leftSideRef.current.style.width = state.leftSideWidth + 'px'
|
|
684
|
+
raf = 0
|
|
685
|
+
})
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
function onUp() {
|
|
689
|
+
removeEventListener('pointermove', onMove)
|
|
690
|
+
cancelAnimationFrame(raf)
|
|
691
|
+
raf = 0
|
|
692
|
+
Object.assign(document.body.style, {
|
|
693
|
+
cursor: 'auto',
|
|
694
|
+
userSelect: 'auto',
|
|
695
|
+
pointerEvents: 'auto'
|
|
696
|
+
})
|
|
697
|
+
}
|
|
698
|
+
|
|
658
699
|
return (
|
|
659
700
|
r('div', {
|
|
660
701
|
className: CSS.Resizer,
|
|
661
|
-
onPointerDown
|
|
702
|
+
onPointerDown
|
|
662
703
|
}))
|
|
663
704
|
}
|
|
664
|
-
Resizer.raf = 0
|
|
665
|
-
Resizer.initialX = 0
|
|
666
|
-
Resizer.panelWidth = 0
|
|
667
|
-
Resizer.onPointerDown = function (event) {
|
|
668
|
-
Resizer.initialX = event.clientX
|
|
669
|
-
Resizer.panelWidth = leftSideRef.current.clientWidth
|
|
670
|
-
addEventListener('pointerup', Resizer.onUp, { once: true })
|
|
671
|
-
addEventListener('pointermove', Resizer.onMove)
|
|
672
|
-
document.body.style.userSelect = 'none'
|
|
673
|
-
document.body.style.cursor = 'col-resize'
|
|
674
|
-
}
|
|
675
|
-
Resizer.onMove = function (event) {
|
|
676
|
-
const MIN_LEFT_WIDTH = 380
|
|
677
|
-
Resizer.raf = Resizer.raf || requestAnimationFrame(() => {
|
|
678
|
-
state.leftSideWidth = Math.max(Resizer.panelWidth - (Resizer.initialX - event.clientX), MIN_LEFT_WIDTH)
|
|
679
|
-
leftSideRef.current.style.width = state.leftSideWidth + 'px'
|
|
680
|
-
Resizer.raf = 0
|
|
681
|
-
})
|
|
682
|
-
}
|
|
683
|
-
Resizer.onUp = function () {
|
|
684
|
-
removeEventListener('pointermove', Resizer.onMove)
|
|
685
|
-
cancelAnimationFrame(Resizer.raf)
|
|
686
|
-
Resizer.raf = 0
|
|
687
|
-
document.body.style.userSelect = 'auto'
|
|
688
|
-
document.body.style.cursor = 'auto'
|
|
689
|
-
}
|
|
690
705
|
|
|
691
706
|
|
|
692
707
|
/** # Payload Preview */
|
|
693
708
|
|
|
694
709
|
const payloadViewerTitleRef = useRef()
|
|
695
|
-
const
|
|
696
|
-
const SPINNER_DELAY = 80
|
|
710
|
+
const payloadViewerCodeRef = useRef()
|
|
697
711
|
|
|
698
712
|
function PayloadViewer() {
|
|
699
713
|
return (
|
|
700
714
|
r('div', className(CSS.PayloadViewer),
|
|
701
715
|
r('h2', { ref: payloadViewerTitleRef }, t`Preview`),
|
|
702
716
|
r('pre', null,
|
|
703
|
-
r('code', { ref:
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
function PayloadViewerProgressBar() {
|
|
707
|
-
return (
|
|
708
|
-
r('div', className(CSS.ProgressBar),
|
|
709
|
-
r('div', { style: { animationDuration: state.delay - SPINNER_DELAY + 'ms' } })))
|
|
717
|
+
r('code', { ref: payloadViewerCodeRef }, t`Click a link to preview it`))))
|
|
710
718
|
}
|
|
711
719
|
|
|
712
720
|
function PayloadViewerTitle({ file, statusText }) {
|
|
713
|
-
const
|
|
714
|
-
const
|
|
715
|
-
const status = tokens.pop()
|
|
716
|
-
const urlAndMethod = tokens.join('.') + '.'
|
|
721
|
+
const { method, status, ext } = parseFilename(file)
|
|
722
|
+
const fileNameWithComments = file.split('.').slice(0, -3).join('.')
|
|
717
723
|
return (
|
|
718
724
|
r('span', null,
|
|
719
|
-
|
|
725
|
+
fileNameWithComments + '.' + method + '.',
|
|
720
726
|
r('abbr', { title: statusText }, status),
|
|
721
727
|
'.' + ext))
|
|
722
728
|
}
|
|
@@ -731,13 +737,20 @@ function PayloadViewerTitleWhenProxied({ mime, status, statusText, gatewayIsBad
|
|
|
731
737
|
' ' + mime))
|
|
732
738
|
}
|
|
733
739
|
|
|
740
|
+
const SPINNER_DELAY = 80
|
|
741
|
+
function PayloadViewerProgressBar() {
|
|
742
|
+
return (
|
|
743
|
+
r('div', className(CSS.ProgressBar),
|
|
744
|
+
r('div', { style: { animationDuration: state.delay - SPINNER_DELAY + 'ms' } })))
|
|
745
|
+
}
|
|
746
|
+
|
|
734
747
|
async function previewMock(method, urlMask) {
|
|
735
748
|
previewMock.controller?.abort()
|
|
736
749
|
previewMock.controller = new AbortController
|
|
737
750
|
|
|
738
751
|
const spinnerTimer = setTimeout(() => {
|
|
739
752
|
payloadViewerTitleRef.current.replaceChildren(t`Fetching…`)
|
|
740
|
-
|
|
753
|
+
payloadViewerCodeRef.current.replaceChildren(PayloadViewerProgressBar())
|
|
741
754
|
}, SPINNER_DELAY)
|
|
742
755
|
|
|
743
756
|
try {
|
|
@@ -746,46 +759,48 @@ async function previewMock(method, urlMask) {
|
|
|
746
759
|
signal: previewMock.controller.signal
|
|
747
760
|
})
|
|
748
761
|
clearTimeout(spinnerTimer)
|
|
749
|
-
|
|
762
|
+
const file = state.fileFor(method, urlMask)
|
|
763
|
+
if (file === '')
|
|
764
|
+
await updatePayloadViewer(STR_PROXIED, response)
|
|
765
|
+
else if (file)
|
|
766
|
+
await updatePayloadViewer(file, response)
|
|
767
|
+
else {/* e.g. selected was deleted */}
|
|
750
768
|
}
|
|
751
769
|
catch (err) {
|
|
752
770
|
onError(err)
|
|
753
|
-
|
|
771
|
+
payloadViewerCodeRef.current.replaceChildren()
|
|
754
772
|
}
|
|
755
773
|
}
|
|
756
774
|
|
|
757
|
-
|
|
758
|
-
async function updatePayloadViewer(method, urlMask, response) {
|
|
775
|
+
async function updatePayloadViewer(file, response) {
|
|
759
776
|
const mime = response.headers.get('content-type') || ''
|
|
760
777
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}))
|
|
778
|
+
payloadViewerTitleRef.current.replaceChildren(
|
|
779
|
+
file === STR_PROXIED
|
|
780
|
+
? PayloadViewerTitleWhenProxied({
|
|
781
|
+
mime,
|
|
782
|
+
status: response.status,
|
|
783
|
+
statusText: response.statusText,
|
|
784
|
+
gatewayIsBad: response.headers.get(HEADER_FOR_502)
|
|
785
|
+
})
|
|
786
|
+
: PayloadViewerTitle({
|
|
787
|
+
file,
|
|
788
|
+
statusText: response.statusText
|
|
789
|
+
}))
|
|
774
790
|
|
|
775
|
-
if (mime.startsWith('image/'))
|
|
776
|
-
|
|
791
|
+
if (mime.startsWith('image/')) // Naively assumes GET.200
|
|
792
|
+
payloadViewerCodeRef.current.replaceChildren(
|
|
777
793
|
r('img', {
|
|
778
794
|
src: URL.createObjectURL(await response.blob())
|
|
779
795
|
}))
|
|
780
|
-
}
|
|
781
796
|
else {
|
|
782
797
|
const body = await response.text() || t`/* Empty Response Body */`
|
|
783
798
|
if (mime === 'application/json')
|
|
784
|
-
|
|
799
|
+
payloadViewerCodeRef.current.replaceChildren(r('span', className(CSS.json), syntaxJSON(body)))
|
|
785
800
|
else if (isXML(mime))
|
|
786
|
-
|
|
801
|
+
payloadViewerCodeRef.current.replaceChildren(syntaxXML(body))
|
|
787
802
|
else
|
|
788
|
-
|
|
803
|
+
payloadViewerCodeRef.current.textContent = body
|
|
789
804
|
}
|
|
790
805
|
}
|
|
791
806
|
|
|
@@ -795,17 +810,6 @@ function isXML(mime) {
|
|
|
795
810
|
}
|
|
796
811
|
|
|
797
812
|
|
|
798
|
-
function mockSelectorFor(method, urlMask) {
|
|
799
|
-
return trFor(method, urlMask)?.querySelector(`select.${CSS.MockSelector}`)
|
|
800
|
-
}
|
|
801
|
-
function trFor(method, urlMask) {
|
|
802
|
-
return document.querySelector(`tr[data-method="${method}"][data-urlMask="${urlMask}"]`)
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
function focus(selector) {
|
|
806
|
-
document.querySelector(selector)?.focus()
|
|
807
|
-
}
|
|
808
|
-
|
|
809
813
|
function initKeyboardNavigation() {
|
|
810
814
|
addEventListener('keydown', onKeyDown)
|
|
811
815
|
|
|
@@ -825,7 +829,7 @@ function initKeyboardNavigation() {
|
|
|
825
829
|
case 'ArrowLeft': {
|
|
826
830
|
if (pivot.hasAttribute('data-focus-group') || pivot.classList.contains(CSS.MockSelector)) {
|
|
827
831
|
const offset = event.key === 'ArrowRight' ? +1 : -1
|
|
828
|
-
rowFocusable(pivot, offset)
|
|
832
|
+
rowFocusable(pivot, offset).focus()
|
|
829
833
|
}
|
|
830
834
|
break
|
|
831
835
|
}
|
|
@@ -850,7 +854,7 @@ function initKeyboardNavigation() {
|
|
|
850
854
|
}
|
|
851
855
|
}
|
|
852
856
|
|
|
853
|
-
/** #
|
|
857
|
+
/** # Error */
|
|
854
858
|
|
|
855
859
|
async function parseError(response) {
|
|
856
860
|
if (response.ok)
|
|
@@ -882,6 +886,9 @@ function showErrorToast(msg) {
|
|
|
882
886
|
}, msg))
|
|
883
887
|
}
|
|
884
888
|
|
|
889
|
+
|
|
890
|
+
/** # Icons */
|
|
891
|
+
|
|
885
892
|
function TimerIcon() {
|
|
886
893
|
return (
|
|
887
894
|
s('svg', { viewBox: '0 0 24 24' },
|
|
@@ -902,43 +909,43 @@ function SettingsIcon() {
|
|
|
902
909
|
}
|
|
903
910
|
|
|
904
911
|
/**
|
|
905
|
-
* #
|
|
906
|
-
* The version increments when a mock file is added or
|
|
912
|
+
* # Long polls UI sync version
|
|
913
|
+
* The version increments when a mock file is added, removed, or renamed.
|
|
907
914
|
*/
|
|
915
|
+
function initRealTimeUpdates() {
|
|
916
|
+
let oldSyncVersion = -1
|
|
917
|
+
let controller = new AbortController()
|
|
908
918
|
|
|
909
|
-
function initLongPoll() {
|
|
910
|
-
poll.oldSyncVersion = -1
|
|
911
|
-
poll.controller = new AbortController()
|
|
912
919
|
poll()
|
|
913
920
|
document.addEventListener('visibilitychange', () => {
|
|
914
921
|
if (document.hidden) {
|
|
915
|
-
|
|
916
|
-
|
|
922
|
+
controller.abort('_hidden_tab_')
|
|
923
|
+
controller = new AbortController()
|
|
917
924
|
}
|
|
918
925
|
else
|
|
919
926
|
poll()
|
|
920
927
|
})
|
|
921
|
-
}
|
|
922
928
|
|
|
923
|
-
async function poll() {
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
929
|
+
async function poll() {
|
|
930
|
+
try {
|
|
931
|
+
const response = await mockaton.getSyncVersion(oldSyncVersion, controller.signal)
|
|
932
|
+
if (response.ok) {
|
|
933
|
+
const syncVersion = await response.json()
|
|
934
|
+
const skipUpdate = oldSyncVersion === -1
|
|
935
|
+
if (oldSyncVersion !== syncVersion) { // because it could be < or >
|
|
936
|
+
oldSyncVersion = syncVersion
|
|
937
|
+
if (!skipUpdate)
|
|
938
|
+
await updateState()
|
|
939
|
+
}
|
|
940
|
+
poll()
|
|
933
941
|
}
|
|
934
|
-
|
|
942
|
+
else
|
|
943
|
+
throw response.status
|
|
944
|
+
}
|
|
945
|
+
catch (error) {
|
|
946
|
+
if (error !== '_hidden_tab_')
|
|
947
|
+
setTimeout(poll, 3000)
|
|
935
948
|
}
|
|
936
|
-
else
|
|
937
|
-
throw response.status
|
|
938
|
-
}
|
|
939
|
-
catch (error) {
|
|
940
|
-
if (error !== '_hidden_tab_')
|
|
941
|
-
setTimeout(poll, 3000)
|
|
942
949
|
}
|
|
943
950
|
}
|
|
944
951
|
|
|
@@ -951,7 +958,6 @@ function className(...args) {
|
|
|
951
958
|
}
|
|
952
959
|
}
|
|
953
960
|
|
|
954
|
-
|
|
955
961
|
function createElement(tag, props, ...children) {
|
|
956
962
|
const node = document.createElement(tag)
|
|
957
963
|
for (const [k, v] of Object.entries(props || {}))
|
|
@@ -998,6 +1004,30 @@ function deferred(cb) {
|
|
|
998
1004
|
: setTimeout(cb, 100) // Safari
|
|
999
1005
|
}
|
|
1000
1006
|
|
|
1007
|
+
function selectorFor(elem) {
|
|
1008
|
+
if (!(elem instanceof Element))
|
|
1009
|
+
return
|
|
1010
|
+
|
|
1011
|
+
const path = []
|
|
1012
|
+
while (elem) {
|
|
1013
|
+
let qualifier = ''
|
|
1014
|
+
if (elem.hasAttribute('key'))
|
|
1015
|
+
qualifier = `[key="${elem.getAttribute('key')}"]`
|
|
1016
|
+
else {
|
|
1017
|
+
let i = 0
|
|
1018
|
+
let sib = elem
|
|
1019
|
+
while ((sib = sib.previousElementSibling))
|
|
1020
|
+
if (sib.tagName === elem.tagName)
|
|
1021
|
+
i++
|
|
1022
|
+
if (i)
|
|
1023
|
+
qualifier = `:nth-of-type(${i + 1})`
|
|
1024
|
+
}
|
|
1025
|
+
path.push(elem.tagName + qualifier)
|
|
1026
|
+
elem = elem.parentElement
|
|
1027
|
+
}
|
|
1028
|
+
return path.reverse().join('>')
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1001
1031
|
|
|
1002
1032
|
// When false, the URL will be updated with param=false
|
|
1003
1033
|
function initPreference(param) {
|
package/src/DashboardHtml.js
CHANGED
|
@@ -9,23 +9,23 @@ export const CSP = [
|
|
|
9
9
|
export const DashboardHtml = `<!DOCTYPE html>
|
|
10
10
|
<html lang="en-US">
|
|
11
11
|
<head>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
<meta charset="UTF-8">
|
|
13
|
+
<base href="${API.dashboard}/">
|
|
14
|
+
|
|
15
|
+
<link rel="stylesheet" href="Dashboard.css">
|
|
16
|
+
<script type="module" src="Dashboard.js"></script>
|
|
17
|
+
|
|
18
18
|
<link rel="preload" href="${API.state}" as="fetch" crossorigin>
|
|
19
19
|
|
|
20
20
|
<link rel="modulepreload" href="ApiConstants.js">
|
|
21
21
|
<link rel="modulepreload" href="ApiCommander.js">
|
|
22
22
|
<link rel="modulepreload" href="Filename.js">
|
|
23
23
|
<link rel="preload" href="Logo.svg" as="image">
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
|
|
25
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m235 33.7v202c0 9.19-5.81 14-17.4 14-11.6 0-17.4-4.83-17.4-14v-151c-0.115-4.49-6.72-5.88-8.46-0.87l-48.3 155c-2.22 7.01-7.72 10.1-16 9.9-3.63-0.191-7.01-1.14-9.66-2.89-2.89-1.72-4.83-4.34-5.57-7.72-11.1-37-22.6-74.3-34.1-111-4.34-14-8.95-31.4-14-48.3-1.82-4.83-8.16-5.32-8.46 1.16v156c0 9.19-5.81 14-17.4 14-11.6 0-17.4-4.83-17.4-14v-207c0-5.74 2.62-13.2 9.39-16.3 7.5-3.14 15-4.05 21.8-3.8 3.14 0 6.03 0.686 8.95 1.46 3.14 0.797 6.03 1.98 8.7 3.63 2.65 1.38 5.32 3.14 7.5 5.57 2.22 2.22 3.87 4.83 5.07 7.72l45.8 157c4.63-15.9 32.4-117 33.3-121 4.12-13.8 7.72-26.5 10.9-38.7 1.16-2.65 2.89-5.32 5.07-7.5 2.15-2.15 4.58-4.12 7.5-5.32 2.65-1.57 5.57-2.89 8.46-3.63 3.14-0.797 9.44-0.988 12.1-0.988 11.6 1.07 29.4 9.14 29.4 27z' fill='%23808080'/%3E%3C/svg%3E">
|
|
26
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
27
|
+
<meta name="description" content="HTTP Mock Server">
|
|
28
|
+
<title>Mockaton</title>
|
|
29
29
|
</head>
|
|
30
30
|
<body>
|
|
31
31
|
</body>
|