mirror of
https://github.com/requarks/wiki.git
synced 2026-08-26 13:17:10 -05:00
feat: table editor (wip) + markdown editor improvements
This commit is contained in:
Generated
+6
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user