Răsfoiți Sursa

feat: admin dev pages modularity + storage state json fix

Nick 6 ani în urmă
părinte
comite
e3cb33f8b5

+ 1 - 0
.gitignore

@@ -32,6 +32,7 @@ server/views/setup.pug
 /data
 /uploads
 /content
+/temp
 *.sqlite
 
 # IDE exclude

+ 19 - 4
client/components/admin.vue

@@ -79,9 +79,22 @@
             v-list-tile(to='/utilities', v-if='hasPermission(`manage:system`)', disabled)
               v-list-tile-avatar: v-icon(color='grey lighten-2') build
               v-list-tile-title {{ $t('admin:utilities.title') }}
-            v-list-tile(to='/dev', v-if='hasPermission([`manage:system`, `manage:api`])')
-              v-list-tile-avatar: v-icon weekend
-              v-list-tile-title {{ $t('admin:dev.title') }}
+            v-list-group(
+              prepend-icon='weekend'
+              value='true'
+              to='/dev'
+              no-action
+              v-if='hasPermission([`manage:system`, `manage:api`])'
+              )
+              v-list-tile(slot='activator')
+                v-list-tile-title {{ $t('admin:dev.title') }}
+
+              v-list-tile(to='/dev-flags')
+                v-list-tile-title {{ $t('admin:dev.flags.title') }}
+              v-list-tile(to='/dev-graphiql')
+                v-list-tile-title {{ $t('admin:dev.graphiql.title') }}
+              v-list-tile(to='/dev-voyager')
+                v-list-tile-title {{ $t('admin:dev.voyager.title') }}
             v-divider.my-2
           v-list-tile(to='/contribute')
             v-list-tile-avatar: v-icon favorite
@@ -132,7 +145,9 @@ const router = new VueRouter({
     { path: '/mail', component: () => import(/* webpackChunkName: "admin" */ './admin/admin-mail.vue') },
     { path: '/system', component: () => import(/* webpackChunkName: "admin" */ './admin/admin-system.vue') },
     { path: '/utilities', component: () => import(/* webpackChunkName: "admin" */ './admin/admin-utilities.vue') },
-    { path: '/dev', component: () => import(/* webpackChunkName: "admin-dev" */ './admin/admin-dev.vue') },
+    { path: '/dev-flags', component: () => import(/* webpackChunkName: "admin-dev" */ './admin/admin-dev-flags.vue') },
+    { path: '/dev-graphiql', component: () => import(/* webpackChunkName: "admin-dev" */ './admin/admin-dev-graphiql.vue') },
+    { path: '/dev-voyager', component: () => import(/* webpackChunkName: "admin-dev" */ './admin/admin-dev-voyager.vue') },
     { path: '/contribute', component: () => import(/* webpackChunkName: "admin" */ './admin/admin-contribute.vue') }
   ]
 })

+ 59 - 0
client/components/admin/admin-dev-flags.vue

@@ -0,0 +1,59 @@
+<template lang='pug'>
+  v-container(fluid, grid-list-lg)
+    v-layout(row, wrap)
+      v-flex(xs12)
+        .admin-header
+          img(src='/svg/icon-console.svg', alt='Developer Tools', style='width: 80px;')
+          .admin-header-title
+            .headline.primary--text Developer Tools
+            .subheading.grey--text Flags
+          v-spacer
+          v-btn(color='success', depressed, @click='save', large)
+            v-icon(left) check
+            span {{$t('common:actions.apply')}}
+
+        v-card.mt-3.white.grey--text.text--darken-3
+          v-alert(color='red', value='true', icon='warning')
+            span Do NOT enable these flags unless you know what you're doing!
+            .caption Doing so may result in data loss or broken installation!
+          v-card-text
+            v-switch.mt-3(
+              color='red'
+              hint='Log all queries made to the database to console.'
+              persistent-hint
+              label='SQL Query Logging'
+              v-model='flags.sqllog'
+            )
+            //- v-divider.mt-3
+            //- v-switch.mt-3(
+            //-   color='primary'
+            //-   hint='Log all queries made to the database to console.'
+            //-   persistent-hint
+            //-   label='SQL Query Log'
+            //-   v-model='flags.sqllog'
+            //- )
+
+</template>
+
+<script>
+import _ from 'lodash'
+
+export default {
+  data() {
+    return {
+      flags: {
+        sqllog: false
+      }
+    }
+  },
+  methods: {
+    save() {
+
+    }
+  }
+}
+</script>
+
+<style lang='scss'>
+
+</style>

+ 101 - 0
client/components/admin/admin-dev-graphiql.vue

@@ -0,0 +1,101 @@
+<template lang='pug'>
+  v-container(fluid, grid-list-lg)
+    v-layout(row, wrap)
+      v-flex(xs12)
+        .admin-header
+          img(src='/svg/icon-console.svg', alt='Developer Tools', style='width: 80px;')
+          .admin-header-title
+            .headline.primary--text Developer Tools
+            .subheading.grey--text GraphiQL
+
+        v-card.mt-3.white.grey--text.text--darken-3
+          #graphiql
+
+</template>
+
+<script>
+import _ from 'lodash'
+import React from 'react'
+import ReactDOM from 'react-dom'
+import GraphiQL from 'graphiql'
+import 'graphiql/graphiql.css'
+
+const fetcher = (qry, respType) => {
+  return fetch('/graphql', {
+    method: 'post',
+    headers: {
+      'Accept': 'application/json',
+      'Content-Type': 'application/json'
+    },
+    body: JSON.stringify(qry),
+    credentials: 'include'
+  }).then(response => {
+    if (respType === 'json') {
+      return response.json()
+    } else {
+      return response.text()
+    }
+  }).then(responseBody => {
+    try {
+      return JSON.parse(responseBody)
+    } catch (error) {
+      return responseBody
+    }
+  })
+}
+
+export default {
+  data() {
+    return { }
+  },
+  mounted() {
+    let graphiQLInstance
+    ReactDOM.render(
+      React.createElement(GraphiQL, {
+        ref(el) { graphiQLInstance = el },
+        async fetcher(qry) {
+          let resp = await fetcher(qry, 'text')
+          _.delay(() => {
+            graphiQLInstance.resultComponent.viewer.refresh()
+          }, 500)
+          return resp
+        },
+        response: null,
+        variables: '{}',
+        operationName: null,
+        websocketConnectionParams: null
+      }),
+      document.getElementById('graphiql')
+    )
+    graphiQLInstance.queryEditorComponent.editor.refresh()
+    graphiQLInstance.variableEditorComponent.editor.refresh()
+    graphiQLInstance.state.variableEditorOpen = true
+    graphiQLInstance.state.docExplorerOpen = true
+  }
+}
+</script>
+
+<style lang='scss'>
+#graphiql {
+  height: calc(100vh - 270px);
+
+  .topBar {
+    background-color: mc('grey', '200');
+    background-image: none;
+    padding: 1.5rem 0;
+
+    > .title {
+      display: none;
+    }
+  }
+
+  .toolbar {
+    background-color: initial;
+    box-shadow: initial;
+  }
+
+  .doc-explorer-title-bar, .history-title-bar {
+    height: auto;
+  }
+}
+</style>

+ 93 - 0
client/components/admin/admin-dev-voyager.vue

@@ -0,0 +1,93 @@
+<template lang='pug'>
+  v-container(fluid, grid-list-lg)
+    v-layout(row, wrap)
+      v-flex(xs12)
+        .admin-header
+          img(src='/svg/icon-console.svg', alt='Developer Tools', style='width: 80px;')
+          .admin-header-title
+            .headline.primary--text Developer Tools
+            .subheading.grey--text Voyager
+
+        v-card.mt-3.white.grey--text.text--darken-3
+          #voyager
+
+</template>
+
+<script>
+import _ from 'lodash'
+import React from 'react'
+import ReactDOM from 'react-dom'
+import { Voyager } from 'graphql-voyager'
+import 'graphql-voyager/dist/voyager.css'
+
+const fetcher = (qry, respType) => {
+  return fetch('/graphql', {
+    method: 'post',
+    headers: {
+      'Accept': 'application/json',
+      'Content-Type': 'application/json'
+    },
+    body: JSON.stringify(qry),
+    credentials: 'include'
+  }).then(response => {
+    if (respType === 'json') {
+      return response.json()
+    } else {
+      return response.text()
+    }
+  }).then(responseBody => {
+    try {
+      return JSON.parse(responseBody)
+    } catch (error) {
+      return responseBody
+    }
+  })
+}
+
+export default {
+  data() {
+    return {}
+  },
+  mounted() {
+    _.delay(() => {
+      ReactDOM.render(
+        React.createElement(Voyager, {
+          introspection: qry => fetcher({ query: qry }, 'json'),
+          workerURI: '/js/voyager.worker.js'
+        }),
+        document.getElementById('voyager')
+      )
+    }, 500)
+  }
+}
+</script>
+
+<style lang='scss'>
+#voyager {
+  height: calc(100vh - 270px);
+
+  .title-area {
+    display: none;
+  }
+  .type-doc {
+    margin-top: 5px;
+  }
+
+  .doc-navigation {
+    > span {
+      overflow-y: hidden;
+      display: block;
+    }
+    min-height: 40px;
+  }
+
+  .contents {
+    padding-bottom: 0;
+    color: #666;
+  }
+
+  .type-info-popover {
+    display: none;
+  }
+}
+</style>

+ 0 - 182
client/components/admin/admin-dev.vue

@@ -1,182 +0,0 @@
-<template lang='pug'>
-  v-container(fluid, grid-list-lg)
-    v-layout(row, wrap)
-      v-flex(xs12)
-        .admin-header
-          img(src='/svg/icon-console.svg', alt='Developer Tools', style='width: 80px;')
-          .admin-header-title
-            .headline.primary--text Developer Tools
-            .subheading.grey--text ¯\_(ツ)_/¯
-          v-spacer
-          v-card.radius-7
-            v-card-text
-              .caption Enables extra dev options and removes many safeguards.
-              .caption.red--text Do not enable unless you know what you're doing!
-              v-switch.mt-1(
-                color='primary'
-                hide-details
-                label='Dev Mode'
-              )
-
-        v-card.mt-3.white.grey--text.text--darken-3
-          v-tabs(
-            v-model='selectedTab'
-            color='grey darken-2'
-            fixed-tabs
-            slider-color='white'
-            show-arrows
-            dark
-            @change='tabChanged'
-            )
-            v-tab(key='0') Graph API Playground
-            v-tab(key='1') Graph API Map
-          v-tabs-items(v-model='selectedTab')
-            v-tab-item(key='0', :transition='false', :reverse-transition='false')
-              #graphiql
-
-            v-tab-item(key='1', :transition='false', :reverse-transition='false')
-              #voyager
-
-</template>
-
-<script>
-import _ from 'lodash'
-import React from 'react'
-import ReactDOM from 'react-dom'
-import GraphiQL from 'graphiql'
-import { Voyager } from 'graphql-voyager'
-import 'graphiql/graphiql.css'
-import 'graphql-voyager/dist/voyager.css'
-
-const fetcher = (qry, respType) => {
-  return fetch('/graphql', {
-    method: 'post',
-    headers: {
-      'Accept': 'application/json',
-      'Content-Type': 'application/json'
-    },
-    body: JSON.stringify(qry),
-    credentials: 'include'
-  }).then(response => {
-    if (respType === 'json') {
-      return response.json()
-    } else {
-      return response.text()
-    }
-  }).then(responseBody => {
-    try {
-      return JSON.parse(responseBody)
-    } catch (error) {
-      return responseBody
-    }
-  })
-}
-
-let graphiQLInstance
-
-export default {
-  data() {
-    return {
-      selectedTab: 0
-    }
-  },
-  mounted() {
-    this.renderGraphiQL()
-  },
-  methods: {
-    tabChanged (tabId) {
-      switch (tabId) {
-        case 1:
-          this.renderVoyager()
-          break
-      }
-    },
-    renderGraphiQL() {
-      ReactDOM.render(
-        React.createElement(GraphiQL, {
-          ref(el) { graphiQLInstance = el },
-          async fetcher(qry) {
-            let resp = await fetcher(qry, 'text')
-            _.delay(() => {
-              graphiQLInstance.resultComponent.viewer.refresh()
-            }, 500)
-            return resp
-          },
-          response: null,
-          variables: '{}',
-          operationName: null,
-          websocketConnectionParams: null
-        }),
-        document.getElementById('graphiql')
-      )
-      graphiQLInstance.queryEditorComponent.editor.refresh()
-      graphiQLInstance.variableEditorComponent.editor.refresh()
-      graphiQLInstance.state.variableEditorOpen = true
-      graphiQLInstance.state.docExplorerOpen = true
-    },
-    renderVoyager() {
-      ReactDOM.render(
-        React.createElement(Voyager, {
-          introspection: qry => fetcher({ query: qry }, 'json'),
-          workerURI: '/js/voyager.worker.js'
-        }),
-        document.getElementById('voyager')
-      )
-    }
-  }
-}
-</script>
-
-<style lang='scss'>
-
-#graphiql {
-  height: calc(100vh - 270px);
-
-  .topBar {
-    background-color: mc('grey', '200');
-    background-image: none;
-    padding: 1.5rem 0;
-
-    > .title {
-      display: none;
-    }
-  }
-
-  .toolbar {
-    background-color: initial;
-    box-shadow: initial;
-  }
-
-  .doc-explorer-title-bar, .history-title-bar {
-    height: auto;
-  }
-}
-
-#voyager {
-  height: calc(100vh - 270px);
-
-  .title-area {
-    display: none;
-  }
-  .type-doc {
-    margin-top: 5px;
-  }
-
-  .doc-navigation {
-    > span {
-      overflow-y: hidden;
-      display: block;
-    }
-    min-height: 40px;
-  }
-
-  .contents {
-    padding-bottom: 0;
-    color: #666;
-  }
-
-  .type-info-popover {
-    display: none;
-  }
-}
-</style>

+ 1 - 1
server/models/storage.js

@@ -28,7 +28,7 @@ module.exports = class Storage extends Model {
   }
 
   static get jsonAttributes() {
-    return ['config']
+    return ['config', 'state']
   }
 
   static async getTargets() {