feat: table editor (wip) + markdown editor improvements

pull/6775/head
Nicolas Giard 2 years ago
parent 33b083c12e
commit 9fb9f53d53
No known key found for this signature in database
GPG Key ID: 85061B8F9D55B7C8

@ -64,6 +64,7 @@
"quasar": "2.11.5",
"slugify": "1.6.5",
"socket.io-client": "4.5.4",
"tabulator-tables": "5.4.4",
"tippy.js": "6.3.7",
"uuid": "9.0.0",
"v-network-graph": "0.8.1",
@ -6714,6 +6715,11 @@
"dev": true,
"license": "MIT"
},
"node_modules/tabulator-tables": {
"version": "5.4.4",
"resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-5.4.4.tgz",
"integrity": "sha512-WqPWLRwrD8UMISUjQqZyj6y9k3ajQBs7eJtRosbt9q8RRkZlYCJYGxLt3L44jEXaQCE5q5EJFbGeDUEDJa1a3w=="
},
"node_modules/tar-stream": {
"version": "2.2.0",
"dev": true,

@ -67,6 +67,7 @@
"quasar": "2.11.5",
"slugify": "1.6.5",
"socket.io-client": "4.5.4",
"tabulator-tables": "5.4.4",
"tippy.js": "6.3.7",
"uuid": "9.0.0",
"v-network-graph": "0.8.1",

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="96px" height="96px"><path fill="#64B5F6" d="M42,37c0,2.762-2.238,5-5,5H11c-2.761,0-5-2.238-5-5V11c0-2.762,2.239-5,5-5h26c2.762,0,5,2.238,5,5V37z"/><path fill="#E3F2FD" d="M17 18h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C18 17.552 17.552 18 17 18M37 18h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C38 17.552 37.552 18 37 18M27 18h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C28 17.552 27.552 18 27 18"/><path fill="#E3F2FD" d="M17 18h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C18 17.552 17.552 18 17 18M37 28h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C38 27.552 37.552 28 37 28M27 28h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C28 27.552 27.552 28 27 28M17 28h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C18 27.552 17.552 28 17 28M37 38h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C38 37.552 37.552 38 37 38M27 38h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C28 37.552 27.552 38 27 38M17 38h-6c-.552 0-1-.448-1-1v-6c0-.552.448-1 1-1h6c.552 0 1 .448 1 1v6C18 37.552 17.552 38 17 38"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -15,6 +15,7 @@
icon='mdi-image-plus-outline'
padding='sm sm'
flat
@click='insertAssets'
)
q-tooltip(anchor='center right' self='center left') {{ t('editor.markup.insertAssets') }}
q-btn(
@ -27,6 +28,7 @@
icon='mdi-table-large-plus'
padding='sm sm'
flat
@click='insertTable'
)
q-tooltip(anchor='center right' self='center left') {{ t('editor.markup.insertTable') }}
q-btn(
@ -39,8 +41,11 @@
icon='mdi-line-scan'
padding='sm sm'
flat
@click='insertHorizontalBar'
)
q-tooltip(anchor='center right' self='center left') {{ t('editor.markup.horizontalBar') }}
q-space
span.editor-markdown-type Markdown
.editor-markdown-mid
//--------------------------------------------------------
//- TOP TOOLBAR
@ -112,6 +117,14 @@
flat
)
q-tooltip(anchor='top middle' self='bottom middle') {{ t('editor.markup.keyboardKey') }}
q-btn(
v-if='!state.previewShown'
icon='mdi-eye-arrow-right-outline'
padding='xs sm'
flat
@click='state.previewShown = true'
)
q-tooltip(anchor='top middle' self='bottom middle') {{ t('editor.togglePreviewPane') }}
//--------------------------------------------------------
//- CODEMIRROR
//--------------------------------------------------------
@ -126,12 +139,15 @@
icon='mdi-arrow-vertical-lock'
padding='xs sm'
flat
@click='state.previewScrollSync = !state.previewScrollSync'
:color='state.previewScrollSync ? `primary` : null'
)
q-tooltip(anchor='top middle' self='bottom middle') {{ t('editor.toggleScrollLock') }}
q-tooltip(anchor='top middle' self='bottom middle') {{ t('editor.toggleScrollSync') }}
q-btn(
icon='mdi-eye-off-outline'
padding='xs sm'
flat
@click='state.previewShown = false'
)
q-tooltip(anchor='top middle' self='bottom middle') {{ t('editor.togglePreviewPane') }}
.editor-markdown-preview-content.contents(ref='editorPreviewContainer')
@ -147,6 +163,7 @@ import { useMeta, useQuasar, setCssVar } from 'quasar'
import { useI18n } from 'vue-i18n'
import { useEditorStore } from 'src/stores/editor'
import { useSiteStore } from 'src/stores/site'
// Code Mirror
import CodeMirror from 'codemirror'
@ -174,6 +191,7 @@ const $q = useQuasar()
// STORES
const editorStore = useEditorStore()
const siteStore = useSiteStore()
// I18N
@ -187,12 +205,48 @@ const cmRef = ref(null)
const state = reactive({
content: '',
previewShown: true,
previewHTML: ''
previewHTML: '',
previewScrollSync: false
})
// Platform detection
const CtrlKey = /Mac/.test(navigator.platform) ? 'Cmd' : 'Ctrl'
// METHODS
function insertAssets () {
siteStore.$patch({
overlay: 'FileManager'
})
}
function insertTable () {
siteStore.$patch({
overlay: 'TableEditor'
})
}
/**
* Insert content at cursor
*/
function insertAtCursor ({ content }) {
const cursor = cm.value.doc.getCursor('head')
cm.value.doc.replaceRange(content, cursor)
}
/**
* Insert content after current line
*/
function insertAfter ({ content, newLine }) {
const curLine = cm.value.doc.getCursor('to').line
const lineLength = cm.value.doc.getLine(curLine).length
cm.value.doc.replaceRange(newLine ? `\n${content}\n` : content, { line: curLine, ch: lineLength + 1 })
}
function insertHorizontalBar () {
insertAfter({ content: '---', newLine: true })
}
// MOUNTED
onMounted(async () => {
@ -339,6 +393,7 @@ $editor-height-mobile: calc(100vh - 112px - 16px);
display: block;
height: $editor-height;
position: relative;
border-right: 5px solid $primary;
}
&-editor {
display: block;
@ -348,6 +403,12 @@ $editor-height-mobile: calc(100vh - 112px - 16px);
// height: $editor-height-mobile;
// }
}
&-type {
writing-mode: vertical-rl;
text-orientation: mixed;
padding-bottom: 1rem;
color: rgba(255,255,255, .4);
}
&-preview {
flex: 1 1 50%;
background-color: $grey-2;

@ -22,6 +22,10 @@ const overlays = {
FileManager: defineAsyncComponent({
loader: () => import('./FileManager.vue'),
loadingComponent: LoadingGeneric
}),
TableEditor: defineAsyncComponent({
loader: () => import('./TableEditorOverlay.vue'),
loadingComponent: LoadingGeneric
})
}

@ -10,6 +10,8 @@
color='primary'
flat
)
q-badge(color='grey' floating rounded)
q-icon(name='las la-pen', size='xs', padding='xs xs')
q-menu(content-class='shadow-7')
icon-picker-dialog(v-model='pageStore.icon')
q-icon.rounded-borders(

@ -0,0 +1,87 @@
<template lang="pug">
q-layout(view='hHh lpR fFf', container)
q-header.card-header.q-px-md.q-py-sm
q-icon(name='img:/_assets/icons/color-data-grid.svg', left, size='md')
span {{t(`editor.tableEditor.title`)}}
q-space
q-btn.q-mr-sm(
flat
rounded
color='white'
:aria-label='t(`common.actions.refresh`)'
icon='las la-question-circle'
:href='siteStore.docsBase + `/admin/editors/markdown`'
target='_blank'
type='a'
)
q-btn-group(push)
q-btn(
push
color='white'
text-color='grey-7'
:label='t(`common.actions.cancel`)'
:aria-label='t(`common.actions.cancel`)'
icon='las la-times'
@click='close'
)
q-btn(
push
color='positive'
text-color='white'
:label='t(`common.actions.save`)'
:aria-label='t(`common.actions.save`)'
icon='las la-check'
:disabled='state.loading > 0'
)
q-page-container
q-page.q-pa-md
div(ref='tblRef')
q-inner-loading(:showing='state.loading > 0')
q-spinner(color='accent', size='lg')
</template>
<script setup>
import { useI18n } from 'vue-i18n'
import { useQuasar } from 'quasar'
import { onMounted, reactive, ref } from 'vue'
import { Tabulator } from 'tabulator-tables'
import gql from 'graphql-tag'
import { cloneDeep } from 'lodash-es'
import { useSiteStore } from 'src/stores/site'
import 'tabulator-tables/dist/css/tabulator.css'
// QUASAR
const $q = useQuasar()
// STORES
const siteStore = useSiteStore()
// I18N
const { t } = useI18n()
// DATA
const state = reactive({
loading: 0
})
const tblRef = ref(null)
// METHODS
function close () {
siteStore.$patch({ overlay: '' })
}
onMounted(() => {
const tbl = new Tabulator(tblRef.value, {
clipboard: true,
height: '100%'
})
})
</script>

@ -1717,7 +1717,8 @@
"profile.cvdTritanopia": "Tritanopia",
"profile.cvdDeuteranopia": "Deuteranopia",
"profile.accessibility": "Accessibility",
"editor.toggleScrollLock": "Toggle Scroll Lock",
"editor.toggleScrollSync": "Toggle Scroll Sync",
"editor.togglePreviewPane": "Toggle Preview Pane",
"editor.renderPreview": "Render Preview"
"editor.renderPreview": "Render Preview",
"editor.tableEditor.title": "Table Editor"
}

@ -52,7 +52,7 @@ q-layout(view='hHh Lpr lff')
q-item-section(side)
q-icon(name='las la-cat', color='white')
q-item-section Installation
q-bar.bg-blue-9.text-white(dense)
q-bar.bg-blue-9.text-white(dense, v-if='flagsStore.experimental')
q-btn.col(
icon='las la-dharmachakra'
label='History'
@ -88,6 +88,7 @@ import { useRouter, useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { useEditorStore } from 'src/stores/editor'
import { useFlagsStore } from 'src/stores/flags'
import { useSiteStore } from 'src/stores/site'
// COMPONENTS
@ -103,6 +104,7 @@ const $q = useQuasar()
// STORES
const editorStore = useEditorStore()
const flagsStore = useFlagsStore()
const siteStore = useSiteStore()
// ROUTER

Loading…
Cancel
Save