Browse Source

feat: content rendering improvements + save fix

pull/760/head
Nicolas Giard 6 years ago
parent
commit
0b5a4e0c63
16 changed files with 125 additions and 48 deletions
  1. 13
      client/client-app.js
  2. 7
      client/components/common/nav-header.vue
  3. 39
      client/components/editor.vue
  4. 8
      client/components/editor/editor-markdown.vue
  5. 16
      client/components/editor/editor-modal-properties.vue
  6. 41
      client/scss/components/v-btn.scss
  7. 11
      client/store/editor.js
  8. 0
      client/themes/default/components/nav-footer.vue
  9. 0
      client/themes/default/components/nav-sidebar.vue
  10. 2
      client/themes/default/components/page.vue
  11. 17
      client/themes/default/scss/app.scss
  12. 9
      server/core/db.js
  13. 5
      server/graph/resolvers/system.js
  14. 2
      server/models/pageHistory.js
  15. 1
      server/views/editor.pug
  16. 2
      server/views/page.pug

13
client/client-app.js

@ -161,14 +161,15 @@ Vue.component('admin', () => import(/* webpackChunkName: "admin" */ './component
Vue.component('editor', () => import(/* webpackPrefetch: -100, webpackChunkName: "editor" */ './components/editor.vue'))
Vue.component('history', () => import(/* webpackChunkName: "history" */ './components/history.vue'))
Vue.component('login', () => import(/* webpackPrefetch: true, webpackChunkName: "login" */ './components/login.vue'))
Vue.component('nav-footer', () => import(/* webpackMode: "eager" */ './components/common/nav-footer.vue'))
Vue.component('nav-header', () => import(/* webpackMode: "eager" */ './components/common/nav-header.vue'))
Vue.component('nav-sidebar', () => import(/* webpackMode: "eager" */ './components/common/nav-sidebar.vue'))
Vue.component('page', () => import(/* webpackChunkName: "theme-page" */ './themes/' + process.env.CURRENT_THEME + '/components/app.vue'))
Vue.component('page-selector', () => import(/* webpackPrefetch: true, webpackChunkName: "ui-extra" */ './components/common/page-selector.vue'))
Vue.component('profile', () => import(/* webpackChunkName: "profile" */ './components/profile.vue'))
Vue.component('v-card-chin', () => import(/* webpackPrefetch: true, webpackChunkName: "ui-extra" */ './components/common/v-card-chin.vue'))
Vue.component('nav-footer', () => import(/* webpackChunkName: "theme-page" */ './themes/' + process.env.CURRENT_THEME + '/components/nav-footer.vue'))
Vue.component('nav-sidebar', () => import(/* webpackChunkName: "theme-page" */ './themes/' + process.env.CURRENT_THEME + '/components/nav-sidebar.vue'))
Vue.component('page', () => import(/* webpackChunkName: "theme-page" */ './themes/' + process.env.CURRENT_THEME + '/components/page.vue'))
let bootstrap = () => {
// ====================================
// Notifications
@ -202,6 +203,12 @@ let bootstrap = () => {
window.boot.notify('vue')
// ====================================
// Load theme-specific code
// ====================================
import(/* webpackChunkName: "theme-page" */ './themes/' + process.env.CURRENT_THEME + '/js/app.js')
// ====================================
// Load Icons
// ====================================

7
client/components/common/nav-header.vue

@ -17,7 +17,7 @@
@keyup.enter='searchEnter'
)
v-menu(open-on-hover, offset-y, bottom, left, min-width='250')
v-toolbar-side-icon(slot='activator')
v-toolbar-side-icon.btn-animate-app(slot='activator')
v-icon view_module
v-list(dense, :light='!$vuetify.dark').py-0
v-list-tile(avatar, href='/')
@ -84,12 +84,12 @@
)
v-icon(color='grey') search
v-tooltip(bottom)
v-btn(icon, href='/a', slot='activator')
v-btn.btn-animate-rotate(icon, href='/a', slot='activator')
v-icon(color='grey') settings
span Admin
v-menu(offset-y, min-width='300')
v-tooltip(bottom, slot='activator')
v-btn(icon, slot='activator')
v-btn.btn-animate-grow(icon, slot='activator', outline, color='grey darken-3')
v-icon(color='grey') account_circle
span Account
v-list.py-0(:light='!$vuetify.dark')
@ -212,4 +212,5 @@ export default {
.navHeaderLoading { // To avoid search bar jumping
width: 22px;
}
</style>

39
client/components/editor.vue

@ -142,6 +142,10 @@ export default {
initContent: {
type: String,
default: null
},
pageId: {
type: Number,
default: 0
}
},
data() {
@ -158,6 +162,7 @@ export default {
notificationState: sync('notification@isActive')
},
created() {
this.$store.commit('page/SET_ID', this.pageId)
this.$store.commit('page/SET_DESCRIPTION', this.description)
this.$store.commit('page/SET_IS_PUBLISHED', this.isPublished)
this.$store.commit('page/SET_LOCALE', this.locale)
@ -212,16 +217,16 @@ export default {
mutation: createPageMutation,
variables: {
content: this.$store.get('editor/content'),
description: this.$store.get('editor/description'),
description: this.$store.get('page/description'),
editor: 'markdown',
locale: this.$store.get('editor/locale'),
locale: this.$store.get('page/locale'),
isPrivate: false,
isPublished: this.$store.get('editor/isPublished'),
path: this.$store.get('editor/path'),
publishEndDate: this.$store.get('editor/publishEndDate'),
publishStartDate: this.$store.get('editor/publishStartDate'),
tags: this.$store.get('editor/tags'),
title: this.$store.get('editor/title')
isPublished: this.$store.get('page/isPublished'),
path: this.$store.get('page/path'),
publishEndDate: this.$store.get('page/publishEndDate'),
publishStartDate: this.$store.get('page/publishStartDate'),
tags: this.$store.get('page/tags'),
title: this.$store.get('page/title')
}
})
resp = _.get(resp, 'data.pages.create', {})
@ -244,18 +249,18 @@ export default {
let resp = await this.$apollo.mutate({
mutation: updatePageMutation,
variables: {
id: this.$store.get('editor/id'),
id: this.$store.get('page/id'),
content: this.$store.get('editor/content'),
description: this.$store.get('editor/description'),
description: this.$store.get('page/description'),
editor: 'markdown',
locale: this.$store.get('editor/locale'),
locale: this.$store.get('page/locale'),
isPrivate: false,
isPublished: this.$store.get('editor/isPublished'),
path: this.$store.get('editor/path'),
publishEndDate: this.$store.get('editor/publishEndDate'),
publishStartDate: this.$store.get('editor/publishStartDate'),
tags: this.$store.get('editor/tags'),
title: this.$store.get('editor/title')
isPublished: this.$store.get('page/isPublished'),
path: this.$store.get('page/path'),
publishEndDate: this.$store.get('page/publishEndDate'),
publishStartDate: this.$store.get('page/publishStartDate'),
tags: this.$store.get('page/tags'),
title: this.$store.get('page/title')
}
})
resp = _.get(resp, 'data.pages.update', {})

8
client/components/editor/editor-markdown.vue

@ -206,7 +206,7 @@ export default {
self.$parent.save()
})
cm.setSize(null, 'calc(100vh - 100px)')
cm.setSize(null, 'calc(100vh - 112px)')
cm.setOption('extraKeys', keyBindings)
cm.on('cursorActivity', cm => {
this.toolbarSync(cm)
@ -270,7 +270,7 @@ export default {
background-color: darken(mc('grey', '900'), 4.5%);
flex: 1 1 50%;
display: block;
height: calc(100vh - 96px);
height: calc(100vh - 112px);
position: relative;
&-title {
@ -300,7 +300,7 @@ export default {
flex: 1 1 50%;
background-color: mc('grey', '100');
position: relative;
height: calc(100vh - 100px);
height: calc(100vh - 112px);
overflow: hidden;
@include until($tablet) {
@ -321,7 +321,7 @@ export default {
}
&-content {
height: calc(100vh - 100px);
height: calc(100vh - 112px);
overflow-y: scroll;
padding: 30px 1rem 1rem 1rem;
width: calc(100% + 1rem + 17px)

16
client/components/editor/editor-modal-properties.vue

@ -207,14 +207,14 @@ export default {
},
computed: {
mode: get('editor/mode'),
title: sync('editor/title'),
description: sync('editor/description'),
locale: sync('editor/locale'),
tags: sync('editor/tags'),
path: sync('editor/path'),
isPublished: sync('editor/isPublished'),
publishStartDate: sync('editor/publishStartDate'),
publishEndDate: sync('editor/publishEndDate')
title: sync('page/title'),
description: sync('page/description'),
locale: sync('page/locale'),
tags: sync('page/tags'),
path: sync('page/path'),
isPublished: sync('page/isPublished'),
publishStartDate: sync('page/publishStartDate'),
publishEndDate: sync('page/publishEndDate')
},
mounted() {
this.isShown = true

41
client/scss/components/v-btn.scss

@ -1,3 +1,44 @@
.v-btn.is-icon {
min-width: auto;
}
.btn-animate-rotate {
i {
transition: all 4s ease;
transform: rotate(0deg);
}
&:hover i {
transform: rotate(360deg);
}
}
.btn-animate-grow {
i {
transition: all 2s ease;
transform: scale(1);
}
&:hover i {
transform: scale(1.25);
}
}
.btn-animate-edit {
i {
transition: all .7s cubic-bezier(0.68, -0.55, 0.265, 1.55);
transform: rotate(0deg);
}
&:hover i {
transform: rotate(-45deg);
}
}
.btn-animate-app {
i {
transition: all .6s ease;
transform: translate3d(0,0,0);
transform-style: preserve-3d;
}
&:hover i {
transform: scale(.7) rotateX(-180deg);
}
}

11
client/store/editor.js

@ -1,17 +1,8 @@
import { make } from 'vuex-pathify'
const state = {
id: 0,
content: '',
description: '',
isPublished: true,
locale: 'en',
mode: 'create',
path: '',
publishEndDate: '',
publishStartDate: '',
tags: [],
title: ''
mode: 'create'
}
export default {

client/components/common/nav-footer.vue → client/themes/default/components/nav-footer.vue

client/components/common/nav-sidebar.vue → client/themes/default/components/nav-sidebar.vue

client/themes/default/components/app.vue → client/themes/default/components/page.vue

@ -47,7 +47,7 @@
.caption.grey--text.text--darken-1 {{ updatedAt | moment('calendar') }}
v-spacer
v-tooltip(left)
v-btn(icon, slot='activator', :href='"/e/" + path')
v-btn.btn-animate-edit(icon, slot='activator', :href='"/e/" + path')
v-icon(color='grey') edit
span Edit Page
v-divider

17
client/themes/default/scss/app.scss

@ -87,16 +87,28 @@
}
code {
background-color: transparent;
background-color: rgba(mc('pink', '500'), .1);
padding: 0 5px;
color: mc('pink', '800');
font-family: 'Source Code Pro', monospace;
font-weight: normal;
font-size: 1rem;
box-shadow: none;
&::before, &::after {
display: none;
}
}
ol, ul {
padding: 1rem 24px 0 24px;
list-style-position: inside;
li + li {
margin-top: .5rem;
}
}
.prismjs{
border: none;
border-radius: 5px;
@ -106,6 +118,9 @@
margin: 1rem 24px;
> code {
background-color: transparent;
padding: 0;
color: #FFF;
box-shadow: initial;
display: block;
font-size: .85rem;

9
server/core/db.js

@ -37,6 +37,15 @@ module.exports = {
case 'mariadb':
case 'mysql':
dbClient = 'mysql2'
// Fix mysql boolean handling...
dbConfig.typeCast = (field, next) => {
if (field.type === 'TINY' && field.length === 1) {
let value = field.string()
return value ? (value === '1') : null
}
return next()
}
break
case 'mssql':
dbClient = 'mssql'

5
server/graph/resolvers/system.js

@ -4,6 +4,7 @@ const getos = Promise.promisify(require('getos'))
const os = require('os')
const filesize = require('filesize')
const path = require('path')
const fs = require('fs-extra')
/* global WIKI */
@ -76,6 +77,10 @@ module.exports = {
const osInfo = await getos()
osLabel = `${os.type()} - ${osInfo.dist} (${osInfo.codename || os.platform()}) ${osInfo.release || os.release()} ${os.arch()}`
}
const isDockerized = await fs.pathExists('/.dockerenv')
if (isDockerized) {
osLabel = `${osLabel} (Docker Container)`
}
return osLabel
},
hostname() {

2
server/models/pageHistory.js

@ -23,6 +23,7 @@ module.exports = class PageHistory extends Model {
publishStartDate: {type: 'string'},
publishEndDate: {type: 'string'},
content: {type: 'string'},
contentType: {type: 'string'},
createdAt: {type: 'string'}
}
@ -87,6 +88,7 @@ module.exports = class PageHistory extends Model {
pageId: opts.id,
authorId: opts.authorId,
content: opts.content,
contentType: opts.contentType,
description: opts.description,
editorKey: opts.editorKey,
hash: opts.hash,

1
server/views/editor.pug

@ -4,6 +4,7 @@ block body
#root
v-app
editor(
:page-id=page.id
locale=page.localeCode
path=page.path
title=page.title

2
server/views/page.pug

@ -14,6 +14,6 @@ block body
updated-at=page.updatedAt
author-name=page.authorName
:author-id=page.authorId
is-published=page.isPublished
:is-published=page.isPublished
)
template(slot='contents')!= page.render
Loading…
Cancel
Save