diff --git a/shells/dev/target/NativeTypes.vue b/shells/dev/target/NativeTypes.vue index 77674e464..11541db3d 100644 --- a/shells/dev/target/NativeTypes.vue +++ b/shells/dev/target/NativeTypes.vue @@ -12,7 +12,12 @@

- +

Set

diff --git a/shells/dev/target/Router.vue b/shells/dev/target/Router.vue deleted file mode 100644 index 935822146..000000000 --- a/shells/dev/target/Router.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - - diff --git a/shells/dev/target/index.js b/shells/dev/target/index.js index 704eb84f1..71832abba 100644 --- a/shells/dev/target/index.js +++ b/shells/dev/target/index.js @@ -7,8 +7,8 @@ import VuexObject from './VuexObject.vue' import NativeTypes from './NativeTypes.vue' import Events from './Events.vue' import MyClass from './MyClass.js' -import Router from './Router.vue' import router from './router' +import Router from './router/Router.vue' window.VUE_DEVTOOLS_CONFIG = { openInEditorHost: '/' @@ -25,6 +25,12 @@ circular.self = circular new Vue({ store, router, + data: { + obj: { + items: items, + circular + } + }, render (h) { return h('div', null, [ h(Counter), @@ -35,12 +41,6 @@ new Vue({ h(Router, { key: [] }), h(VuexObject) ]) - }, - data: { - obj: { - items: items, - circular - } } }).$mount('#app') diff --git a/shells/dev/target/router.js b/shells/dev/target/router.js index d0a703526..1b37e0d8f 100644 --- a/shells/dev/target/router.js +++ b/shells/dev/target/router.js @@ -1,13 +1,49 @@ import Vue from 'vue' import VueRouter from 'vue-router' -import Page1 from './Page1.vue' -import Page2 from './Page2.vue' +import RouteOne from './router/RouteOne.vue' +import RouteTwo from './router/RouteTwo.vue' +import RouteWithParams from './router/RouteWithParams.vue' +import NamedRoute from './router/NamedRoute.vue' +import RouteWithQuery from './router/RouteWithQuery.vue' +import RouteWithBeforeEnter from './router/RouteWithBeforeEnter.vue' +import RouteWithAlias from './router/RouteWithAlias.vue' +import RouteWithProps from './router/RouteWithProps.vue' +import ParentRoute from './router/ParentRoute.vue' +import ChildRoute from './router/ChildRoute.vue' Vue.use(VueRouter) +const DynamicComponent = { + render: (h) => h('div', 'Hello from dynamic component') +} + const routes = [ - { path: '/', name: 'page1', component: Page1 }, - { path: '/page2', name: 'page2', component: Page2 } + { path: '/route-one', component: RouteOne }, + { path: '/route-two', component: RouteTwo }, + { path: '/route-with-params/:username/:id', component: RouteWithParams }, + { path: '/route-named', component: NamedRoute, name: 'NamedRoute' }, + { path: '/route-with-query', component: RouteWithQuery }, + { path: '/route-with-before-enter', + component: RouteWithBeforeEnter, + beforeEnter: (to, from, next) => { + next() + }}, + { path: '/route-with-redirect', redirect: '/route-one' }, + { path: '/route-with-alias', component: RouteWithAlias, alias: '/this-is-the-alias' }, + { path: '/route-with-dynamic-component', component: DynamicComponent, props: true }, + { path: '/route-with-props', + component: RouteWithProps, + props: { + username: 'My Username', + id: 99 + }}, + { path: '/route-with-props-default', component: RouteWithProps }, + { path: '/route-parent', + component: ParentRoute, + children: [ + { path: '/route-child', component: ChildRoute } + ] + } ] const router = new VueRouter({ diff --git a/shells/dev/target/router/ChildRoute.vue b/shells/dev/target/router/ChildRoute.vue new file mode 100644 index 000000000..3337f2ee4 --- /dev/null +++ b/shells/dev/target/router/ChildRoute.vue @@ -0,0 +1,9 @@ + + + diff --git a/shells/dev/target/router/NamedRoute.vue b/shells/dev/target/router/NamedRoute.vue new file mode 100644 index 000000000..e68fd580b --- /dev/null +++ b/shells/dev/target/router/NamedRoute.vue @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/shells/dev/target/router/ParentRoute.vue b/shells/dev/target/router/ParentRoute.vue new file mode 100644 index 000000000..27138e6d6 --- /dev/null +++ b/shells/dev/target/router/ParentRoute.vue @@ -0,0 +1,12 @@ + + + diff --git a/shells/dev/target/router/RouteOne.vue b/shells/dev/target/router/RouteOne.vue new file mode 100644 index 000000000..b131fd159 --- /dev/null +++ b/shells/dev/target/router/RouteOne.vue @@ -0,0 +1,11 @@ + + + diff --git a/shells/dev/target/router/RouteTwo.vue b/shells/dev/target/router/RouteTwo.vue new file mode 100644 index 000000000..ffa59b0ad --- /dev/null +++ b/shells/dev/target/router/RouteTwo.vue @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/shells/dev/target/router/RouteWithAlias.vue b/shells/dev/target/router/RouteWithAlias.vue new file mode 100644 index 000000000..0a67a2ec8 --- /dev/null +++ b/shells/dev/target/router/RouteWithAlias.vue @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/shells/dev/target/router/RouteWithBeforeEnter.vue b/shells/dev/target/router/RouteWithBeforeEnter.vue new file mode 100644 index 000000000..479291b0a --- /dev/null +++ b/shells/dev/target/router/RouteWithBeforeEnter.vue @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/shells/dev/target/router/RouteWithParams.vue b/shells/dev/target/router/RouteWithParams.vue new file mode 100644 index 000000000..0b8db1849 --- /dev/null +++ b/shells/dev/target/router/RouteWithParams.vue @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/shells/dev/target/router/RouteWithProps.vue b/shells/dev/target/router/RouteWithProps.vue new file mode 100644 index 000000000..34e7af10a --- /dev/null +++ b/shells/dev/target/router/RouteWithProps.vue @@ -0,0 +1,20 @@ + + + \ No newline at end of file diff --git a/shells/dev/target/router/RouteWithQuery.vue b/shells/dev/target/router/RouteWithQuery.vue new file mode 100644 index 000000000..759da6f26 --- /dev/null +++ b/shells/dev/target/router/RouteWithQuery.vue @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/shells/dev/target/router/Router.vue b/shells/dev/target/router/Router.vue new file mode 100644 index 000000000..ffdb05fb3 --- /dev/null +++ b/shells/dev/target/router/Router.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/backend/index.js b/src/backend/index.js index 489c94dba..b7ca82eea 100644 --- a/src/backend/index.js +++ b/src/backend/index.js @@ -4,6 +4,7 @@ import { highlight, unHighlight, getInstanceOrVnodeRect } from './highlighter' import { initVuexBackend } from './vuex' import { initEventsBackend } from './events' +import { initRouterBackend } from './router' import { initPerfBackend } from './perf' import { findRelatedComponent } from './utils' import { stringify, classify, camelize, set, parse, getComponentName } from '../util' @@ -121,6 +122,10 @@ function connect (Vue) { }) } + hook.once('router:init', () => { + initRouterBackend(hook.Vue, bridge, rootInstances) + }) + // events initEventsBackend(Vue, bridge) @@ -206,6 +211,7 @@ function scan () { return true } }) + hook.emit('router:init') flush() } @@ -340,7 +346,7 @@ function capture (instance, index, list) { captureCount++ } - if (instance.$options && instance.$options.abstract) { + if (instance.$options && instance.$options.abstract && instance._vnode.componentInstance) { instance = instance._vnode.componentInstance } diff --git a/src/backend/perf.js b/src/backend/perf.js index f52511adb..ec29d0a49 100644 --- a/src/backend/perf.js +++ b/src/backend/perf.js @@ -95,8 +95,10 @@ function applyHooks (vm) { if (renderHook && renderHook.before) { // Render hook ends before one hook const metric = renderMetrics[renderHook.before] - metric.end = time - addComponentMetric(vm.$options, renderHook.before, metric.start, metric.end) + if (metric) { + metric.end = time + addComponentMetric(vm.$options, renderHook.before, metric.start, metric.end) + } } // After diff --git a/src/backend/router.js b/src/backend/router.js index a7a9f1970..a5af0a539 100644 --- a/src/backend/router.js +++ b/src/backend/router.js @@ -1,3 +1,61 @@ +import { stringify } from '../util' + +export function initRouterBackend (Vue, bridge, rootInstances) { + let recording = true + + const getSnapshot = () => { + const routeChanges = [] + rootInstances.forEach(instance => { + const router = instance._router + if (router && router.options && router.options.routes) { + routeChanges.push(...router.options.routes) + } + }) + return stringify({ + routeChanges + }) + } + + bridge.send('routes:init', getSnapshot()) + + bridge.on('router:toggle-recording', enabled => { + recording = enabled + }) + + rootInstances.forEach(instance => { + const router = instance._router + + if (router) { + router.afterEach((to, from) => { + if (!recording) return + bridge.send('router:changed', stringify({ + to, + from, + timestamp: Date.now() + })) + }) + bridge.send('router:init', stringify({ + mode: router.mode, + current: { + from: router.history.current, + to: router.history.current, + timestamp: Date.now() + } + })) + + if (router.matcher && router.matcher.addRoutes) { + const addRoutes = router.matcher.addRoutes + router.matcher.addRoutes = function (routes) { + routes.forEach((item) => { + bridge.send('routes:changed', stringify(item)) + }) + addRoutes.call(this, routes) + } + } + } + }) +} + export function getCustomRouterDetails (router) { return { _custom: { diff --git a/src/devtools/App.vue b/src/devtools/App.vue index 631b1392b..11e3da1a9 100644 --- a/src/devtools/App.vue +++ b/src/devtools/App.vue @@ -76,9 +76,46 @@ value="events" icon-left="grain" class="events-tab flat big-tag" + @focus.native="isRouterGroupOpen = false" > Events + + + + Settings @@ -126,8 +164,11 @@ import ComponentsTab from './views/components/ComponentsTab.vue' import EventsTab from './views/events/EventsTab.vue' import VuexTab from './views/vuex/VuexTab.vue' +import RouterTab from './views/router/RouterTab.vue' +import RoutesTab from './views/routes/RoutesTab.vue' import { SPECIAL_TOKENS } from '../util' import Keyboard from './mixins/keyboard' +import GroupDropdown from 'components/GroupDropdown.vue' import { mapState } from 'vuex' @@ -137,7 +178,10 @@ export default { components: { components: ComponentsTab, vuex: VuexTab, - events: EventsTab + events: EventsTab, + router: RouterTab, + routes: RoutesTab, + GroupDropdown }, mixins: [ @@ -161,9 +205,15 @@ export default { this.$router.push({ name: 'events' }) return false } else if (code === 'Digit4') { + if (this.$route.name !== 'router') { + this.$router.push({ name: 'router' }) + } else { + this.$router.push({ name: 'routes' }) + } + } else if (code === 'Digit5') { this.$router.push({ name: 'perf' }) return false - } else if (code === 'Digit5') { + } else if (code === 'Digit6') { this.$router.push({ name: 'settings' }) return false } else if (key === 'p' || code === 'KeyP') { @@ -175,6 +225,16 @@ export default { }) ], + data () { + return { + isRouterGroupOpen: false, + routingTabs: [ + { name: 'router', label: 'History', icon: 'directions' }, + { name: 'routes', label: 'Routes', icon: 'book' } + ] + } + }, + computed: { ...mapState({ message: state => state.message, @@ -326,4 +386,8 @@ export default { .container overflow hidden flex 1 + +.hide-below-wide + @media (max-width: $wide) + display: none diff --git a/src/devtools/components/GroupDropdown.vue b/src/devtools/components/GroupDropdown.vue new file mode 100644 index 000000000..cbd41dd5b --- /dev/null +++ b/src/devtools/components/GroupDropdown.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/src/devtools/components/SplitPane.vue b/src/devtools/components/SplitPane.vue index 5057ddc7e..fc80b37cc 100644 --- a/src/devtools/components/SplitPane.vue +++ b/src/devtools/components/SplitPane.vue @@ -154,5 +154,4 @@ export default { bottom -5px height 10px cursor ns-resize - diff --git a/src/devtools/components/TriplePane.vue b/src/devtools/components/TriplePane.vue new file mode 100644 index 000000000..2102b0677 --- /dev/null +++ b/src/devtools/components/TriplePane.vue @@ -0,0 +1,73 @@ + + + diff --git a/src/devtools/components/splitPanes.styl b/src/devtools/components/splitPanes.styl new file mode 100644 index 000000000..2a5ba77c5 --- /dev/null +++ b/src/devtools/components/splitPanes.styl @@ -0,0 +1,22 @@ +.split-pane + display flex + height 100% + &.dragging + cursor ew-resize + +.left, .right, .middle + position relative + +.left, .middle + border-right 1px solid $border-color + .app.dark & + border-right 1px solid $dark-border-color + +.dragger + position absolute + z-index 99 + top 0 + bottom 0 + right -5px + width 10px + cursor ew-resize \ No newline at end of file diff --git a/src/devtools/index.js b/src/devtools/index.js index fcef10edb..cdd71b573 100644 --- a/src/devtools/index.js +++ b/src/devtools/index.js @@ -169,6 +169,27 @@ function initApp (shell) { } }) + bridge.on('router:init', payload => { + store.commit('router/INIT', parse(payload)) + }) + + bridge.on('router:changed', payload => { + store.commit('router/CHANGED', parse(payload)) + }) + + bridge.on('routes:init', payload => { + store.commit('routes/INIT', parse(payload)) + }) + + bridge.on('routes:changed', payload => { + store.commit('routes/CHANGED', parse(payload)) + }) + + // register filters + Vue.filter('formatTime', function (timestamp) { + return (new Date(timestamp)).toString().match(/\d\d:\d\d:\d\d/)[0] + }) + bridge.on('events:reset', () => { store.commit('events/RESET') }) diff --git a/src/devtools/locales/en.js b/src/devtools/locales/en.js index 922129717..d211f749a 100644 --- a/src/devtools/locales/en.js +++ b/src/devtools/locales/en.js @@ -9,11 +9,14 @@ export default { refresh: { tooltip: '[[{{keys.ctrl}}]] + [[{{keys.alt}}]] + [[R]] Force Refresh' }, + routing: { + tooltip: '[[{{keys.ctrl}}]] + [[4]] Switch to Routing' + }, perf: { - tooltip: '[[{{keys.ctrl}}]] + [[4]] Switch to Performance' + tooltip: '[[{{keys.ctrl}}]] + [[5]] Switch to Performance' }, settings: { - tooltip: '[[{{keys.ctrl}}]] + [[5]] Switch to Settings' + tooltip: '[[{{keys.ctrl}}]] + [[6]] Switch to Settings' }, vuex: { tooltip: '[[{{keys.ctrl}}]] + [[2]] Switch to Vuex' diff --git a/src/devtools/router.js b/src/devtools/router.js index d93f93503..7b7d24062 100644 --- a/src/devtools/router.js +++ b/src/devtools/router.js @@ -8,6 +8,8 @@ import PerfTab from './views/perf/PerfTab.vue' import ComponentRenderStats from './views/perf/ComponentRenderStats.vue' import FramerateGraph from './views/perf/FramerateGraph.vue' import SettingsTab from './views/settings/SettingsTab.vue' +import RouterTab from './views/router/RouterTab.vue' +import RoutesTab from './views/routes/RoutesTab.vue' Vue.use(VueRouter) @@ -31,6 +33,16 @@ const routes = [ name: 'events', component: EventsTab }, + { + path: '/router', + name: 'router', + component: RouterTab + }, + { + path: '/routes', + name: 'routes', + component: RoutesTab + }, { path: '/perf', component: PerfTab, diff --git a/src/devtools/store/index.js b/src/devtools/store/index.js index 679131dac..a7956b564 100644 --- a/src/devtools/store/index.js +++ b/src/devtools/store/index.js @@ -3,6 +3,8 @@ import Vuex from 'vuex' import components from 'views/components/module' import vuex from 'views/vuex/module' import events from 'views/events/module' +import router from 'views/router/module' +import routes from 'views/routes/module' import perf from 'views/perf/module' Vue.use(Vuex) @@ -27,6 +29,8 @@ const store = new Vuex.Store({ components, vuex, events, + router, + routes, perf } }) @@ -38,6 +42,8 @@ if (module.hot) { 'views/components/module', 'views/vuex/module', 'views/events/module', + 'views/router/module', + 'views/routes/module', 'views/perf/module' ], () => { try { @@ -46,6 +52,8 @@ if (module.hot) { components: require('views/components/module').default, vuex: require('views/vuex/module').default, events: require('views/events/module').default, + router: require('views/router/module').default, + routes: require('views/routes/module').default, perf: require('views/perf/module').default } }) diff --git a/src/devtools/style/variables.styl b/src/devtools/style/variables.styl index 8e22d9bd3..e246a95c2 100644 --- a/src/devtools/style/variables.styl +++ b/src/devtools/style/variables.styl @@ -32,3 +32,47 @@ $dark-border-color = lighten($vue-ui-color-darker, 10%) $dark-background-color = $vue-ui-color-darker $dark-component-color = $active-color $dark-hover-color = $vue-ui-color-dark + +// Entries +// TODO: FIX THIS +// .no-entries +// color: #ccc +// text-align: center +// margin-top: 50px +// line-height: 30px +// +// .entry +// position: relative; +// font-family Menlo, Consolas, monospace +// color #881391 +// cursor pointer +// padding 10px 20px +// font-size 12px +// background-color $background-color +// box-shadow 0 1px 5px rgba(0,0,0,.12) +// .entry-name +// font-weight 600 +// .entry-source +// color #999 +// .component-name +// color $component-color +// .entry-type +// color #999 +// margin-left 8px +// &.active +// color #fff +// background-color $active-color +// .time, .entry-type, .component-name +// color lighten($active-color, 75%) +// .entry-name +// color: #fff +// .entry-source +// color #ddd +// .app.dark & +// background-color $dark-background-color +// +// .time +// font-size 11px +// color #999 +// float right +// margin-top 3px diff --git a/src/devtools/views/perf/FramerateGraph.vue b/src/devtools/views/perf/FramerateGraph.vue index 239ef1206..70a0ffa02 100644 --- a/src/devtools/views/perf/FramerateGraph.vue +++ b/src/devtools/views/perf/FramerateGraph.vue @@ -76,7 +76,8 @@ import FramerateMarkerInspector from './FramerateMarkerInspector.vue' const BUBBLE_COLORS = { mutations: '#FF6B00', - events: '#997fff' + events: '#997fff', + routes: '#42B983' } // In ms diff --git a/src/devtools/views/perf/module.js b/src/devtools/views/perf/module.js index d9f810fa5..51c1f2dc6 100644 --- a/src/devtools/views/perf/module.js +++ b/src/devtools/views/perf/module.js @@ -65,6 +65,15 @@ export default { } })) + const { routeChanges } = rootState.router + addEntries('routes', routeChanges, entry => ({ + label: entry.to.fullPath, + state: { + 'from': entry.from, + 'to': entry.to + } + })) + return markers } }, diff --git a/src/devtools/views/router/RouterHistory.vue b/src/devtools/views/router/RouterHistory.vue new file mode 100644 index 000000000..4a9432f65 --- /dev/null +++ b/src/devtools/views/router/RouterHistory.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/src/devtools/views/router/RouterMeta.vue b/src/devtools/views/router/RouterMeta.vue new file mode 100644 index 000000000..f0a305990 --- /dev/null +++ b/src/devtools/views/router/RouterMeta.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/src/devtools/views/router/RouterTab.vue b/src/devtools/views/router/RouterTab.vue new file mode 100644 index 000000000..6e5f71ac7 --- /dev/null +++ b/src/devtools/views/router/RouterTab.vue @@ -0,0 +1,31 @@ + + + diff --git a/src/devtools/views/router/module.js b/src/devtools/views/router/module.js new file mode 100644 index 000000000..fb34265c2 --- /dev/null +++ b/src/devtools/views/router/module.js @@ -0,0 +1,61 @@ +import storage from '../../storage' + +const ENABLED_KEY = 'EVENTS_ENABLED' +const enabled = storage.get(ENABLED_KEY) + +const state = { + enabled: enabled == null ? true : enabled, + hasRouter: false, + instances: [], + routeChanges: [], + inspectedIndex: -1, + filter: '' +} + +const mutations = { + 'INIT' (state, payload) { + state.instances = [] + state.routeChanges = [payload.current] + state.inspectedIndex = -1 + state.hasRouter = true + state.instances.push(payload) + }, + 'RESET' (state) { + state.routeChanges = [] + state.inspectedIndex = -1 + }, + 'CHANGED' (state, payload) { + state.routeChanges.push(payload) + if (!state.filter) { + state.inspectedIndex = state.routeChanges.length - 1 + } + }, + 'INSPECT' (state, index) { + state.inspectedIndex = index + }, + 'UPDATE_FILTER' (state, filter) { + state.filter = filter + }, + 'TOGGLE' (state) { + storage.set(ENABLED_KEY, state.enabled = !state.enabled) + bridge.send('router:toggle-recording', state.enabled) + } +} + +const getters = { + activeRouteChange: state => { + return state.routeChanges[state.inspectedIndex] + }, + filteredRoutes: state => { + return state.routeChanges.filter(routeChange => { + return routeChange.from.fullPath.indexOf(state.filter) > -1 || routeChange.to.fullPath.indexOf(state.filter) > -1 + }) + } +} + +export default { + namespaced: true, + state, + mutations, + getters +} diff --git a/src/devtools/views/routes/RouteMeta.vue b/src/devtools/views/routes/RouteMeta.vue new file mode 100644 index 000000000..b9b35fca1 --- /dev/null +++ b/src/devtools/views/routes/RouteMeta.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/src/devtools/views/routes/RouterTab.vue b/src/devtools/views/routes/RouterTab.vue new file mode 100644 index 000000000..a7aad9ada --- /dev/null +++ b/src/devtools/views/routes/RouterTab.vue @@ -0,0 +1,39 @@ + + + diff --git a/src/devtools/views/routes/RoutesHistory.vue b/src/devtools/views/routes/RoutesHistory.vue new file mode 100644 index 000000000..4a9432f65 --- /dev/null +++ b/src/devtools/views/routes/RoutesHistory.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/src/devtools/views/routes/RoutesMeta.vue b/src/devtools/views/routes/RoutesMeta.vue new file mode 100644 index 000000000..92b7ef120 --- /dev/null +++ b/src/devtools/views/routes/RoutesMeta.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/src/devtools/views/routes/RoutesTab.vue b/src/devtools/views/routes/RoutesTab.vue new file mode 100644 index 000000000..b4beb9fe5 --- /dev/null +++ b/src/devtools/views/routes/RoutesTab.vue @@ -0,0 +1,31 @@ + + + diff --git a/src/devtools/views/routes/RoutesTree.vue b/src/devtools/views/routes/RoutesTree.vue new file mode 100644 index 000000000..061cb7907 --- /dev/null +++ b/src/devtools/views/routes/RoutesTree.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/src/devtools/views/routes/RoutesTreeItem.vue b/src/devtools/views/routes/RoutesTreeItem.vue new file mode 100644 index 000000000..1996149ab --- /dev/null +++ b/src/devtools/views/routes/RoutesTreeItem.vue @@ -0,0 +1,186 @@ + + + + + diff --git a/src/devtools/views/routes/module.js b/src/devtools/views/routes/module.js new file mode 100644 index 000000000..cb1c1710b --- /dev/null +++ b/src/devtools/views/routes/module.js @@ -0,0 +1,62 @@ +import storage from '../../storage' + +const ENABLED_KEY = 'EVENTS_ENABLED' +const enabled = storage.get(ENABLED_KEY) + +const state = { + enabled: enabled == null ? true : enabled, + hasRouter: false, + routeChanges: [], + inspectedIndex: -1, + filter: '' +} + +const mutations = { + INIT (state, payload) { + state.inspectedIndex = -1 + state.hasRouter = true + state.routeChanges = payload.routeChanges + }, + CHANGED (state, payload) { + state.routeChanges.push(payload) + }, + INSPECT (state, index) { + state.inspectedIndex = index + }, + UPDATE_FILTER (state, filter) { + state.filter = filter + } +} + +const getters = { + activeRouteChange: state => { + if (typeof state.inspectedIndex === 'string') { + const path = state.inspectedIndex.split('_') + let obj = state.routeChanges[parseInt(path[0])] + for (var i = 1, len = path.length; i < len; ++i) { + obj = obj.children[parseInt(path[i])] + } + return obj + } + return state.routeChanges[state.inspectedIndex] + }, + activeRoute: (state, getters, rootState) => { + return state.routeChanges.find( + change => rootState.router.routeChanges.find( + historyChange => historyChange.to.path === change.path + ) + ) + }, + filteredRoutes: state => { + return state.routeChanges.filter(routeChange => { + return routeChange.path.indexOf(state.filter) > -1 + }) + } +} + +export default { + namespaced: true, + state, + mutations, + getters +}