Compare commits
2 Commits
feat/git-s
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0fa8f951ae | |||
| cdc9652842 |
@@ -7,7 +7,7 @@ name: build-and-push
|
|||||||
# (ingen insecure-registry-config behövs där).
|
# (ingen insecure-registry-config behövs där).
|
||||||
#
|
#
|
||||||
# Pull:a på Pi5 med localhost:5000/archivum:latest (t.ex. i dockge-stacken).
|
# Pull:a på Pi5 med localhost:5000/archivum:latest (t.ex. i dockge-stacken).
|
||||||
# rebuild trigger: 2 (previous run was interrupted by a host overload)
|
# rebuild trigger: 3 (run #8 hit a transient TLS timeout pulling alpine:3.20)
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main, master]
|
branches: [main, master]
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
||||||
import { EditorView, basicSetup } from 'codemirror'
|
import { EditorView, basicSetup } from 'codemirror'
|
||||||
import { EditorState } from '@codemirror/state'
|
import { EditorState, Compartment } from '@codemirror/state'
|
||||||
import { markdown } from '@codemirror/lang-markdown'
|
import { markdown } from '@codemirror/lang-markdown'
|
||||||
import { oneDark } from '@codemirror/theme-one-dark'
|
import { oneDark } from '@codemirror/theme-one-dark'
|
||||||
|
|
||||||
const model = defineModel<string>({ required: true })
|
const model = defineModel<string>({ required: true })
|
||||||
|
const props = withDefaults(defineProps<{ readonly?: boolean }>(), { readonly: false })
|
||||||
const container = ref<HTMLElement | null>(null)
|
const container = ref<HTMLElement | null>(null)
|
||||||
let view: EditorView | null = null
|
let view: EditorView | null = null
|
||||||
|
|
||||||
|
const readonlyCompartment = new Compartment()
|
||||||
|
const readonlyExtensions = (ro: boolean) => [EditorState.readOnly.of(ro), EditorView.editable.of(!ro)]
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!container.value) return
|
if (!container.value) return
|
||||||
|
|
||||||
@@ -20,6 +24,7 @@ onMounted(() => {
|
|||||||
basicSetup,
|
basicSetup,
|
||||||
markdown(),
|
markdown(),
|
||||||
oneDark,
|
oneDark,
|
||||||
|
readonlyCompartment.of(readonlyExtensions(props.readonly)),
|
||||||
EditorView.updateListener.of((update) => {
|
EditorView.updateListener.of((update) => {
|
||||||
if (update.docChanged) {
|
if (update.docChanged) {
|
||||||
model.value = update.state.doc.toString()
|
model.value = update.state.doc.toString()
|
||||||
@@ -30,6 +35,10 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(() => props.readonly, (ro) => {
|
||||||
|
view?.dispatch({ effects: readonlyCompartment.reconfigure(readonlyExtensions(ro)) })
|
||||||
|
})
|
||||||
|
|
||||||
// Sync external model changes into CodeMirror.
|
// Sync external model changes into CodeMirror.
|
||||||
watch(model, (adoc) => {
|
watch(model, (adoc) => {
|
||||||
if (!view) return
|
if (!view) return
|
||||||
|
|||||||
@@ -14,9 +14,15 @@ import ImageEditDialog from './ImageEditDialog.vue'
|
|||||||
import LinkDialog from './LinkDialog.vue'
|
import LinkDialog from './LinkDialog.vue'
|
||||||
|
|
||||||
const model = defineModel<string>({ required: true })
|
const model = defineModel<string>({ required: true })
|
||||||
const props = defineProps<{ slug?: string }>()
|
const props = withDefaults(defineProps<{ slug?: string; editable?: boolean }>(), { editable: true })
|
||||||
|
|
||||||
const isEditing = ref(false)
|
const isEditing = ref(false)
|
||||||
|
|
||||||
|
// Force read mode if edit permission disappears (e.g. navigating to a doc
|
||||||
|
// the user may not edit while this component instance is reused).
|
||||||
|
watch(() => props.editable, (editable) => {
|
||||||
|
if (!editable) isEditing.value = false
|
||||||
|
})
|
||||||
const showImagePicker = ref(false)
|
const showImagePicker = ref(false)
|
||||||
const showImageEditor = ref(false)
|
const showImageEditor = ref(false)
|
||||||
const showLinkDialog = ref({ open: false, url: '', text: '' })
|
const showLinkDialog = ref({ open: false, url: '', text: '' })
|
||||||
@@ -473,9 +479,9 @@ function handleEditorClick(e: MouseEvent) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Banner when not editing -->
|
<!-- Banner when not editing (hidden entirely without edit permission) -->
|
||||||
<div
|
<div
|
||||||
v-if="!isEditing"
|
v-if="!isEditing && props.editable"
|
||||||
class="bg-indigo-50 dark:bg-slate-800/80 border-b border-indigo-100 dark:border-slate-700/60 flex items-center justify-between p-2 flex-shrink-0"
|
class="bg-indigo-50 dark:bg-slate-800/80 border-b border-indigo-100 dark:border-slate-700/60 flex items-center justify-between p-2 flex-shrink-0"
|
||||||
>
|
>
|
||||||
<span class="text-sm text-indigo-700 dark:text-indigo-300 ml-2">Läsläge</span>
|
<span class="text-sm text-indigo-700 dark:text-indigo-300 ml-2">Läsläge</span>
|
||||||
|
|||||||
@@ -357,11 +357,13 @@ function formatDate(dateStr: string) {
|
|||||||
<VisualEditor
|
<VisualEditor
|
||||||
v-else-if="versionEditorMode === 'visual'"
|
v-else-if="versionEditorMode === 'visual'"
|
||||||
:slug="slug"
|
:slug="slug"
|
||||||
|
:editable="false"
|
||||||
:model-value="versionContent"
|
:model-value="versionContent"
|
||||||
@update:model-value="() => {}"
|
@update:model-value="() => {}"
|
||||||
/>
|
/>
|
||||||
<SourceEditor
|
<SourceEditor
|
||||||
v-else
|
v-else
|
||||||
|
readonly
|
||||||
:model-value="versionContent"
|
:model-value="versionContent"
|
||||||
@update:model-value="() => {}"
|
@update:model-value="() => {}"
|
||||||
/>
|
/>
|
||||||
@@ -370,8 +372,8 @@ function formatDate(dateStr: string) {
|
|||||||
<!-- Normal editor -->
|
<!-- Normal editor -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div v-if="loading" class="p-6 text-slate-400 animate-pulse">Loading…</div>
|
<div v-if="loading" class="p-6 text-slate-400 animate-pulse">Loading…</div>
|
||||||
<VisualEditor v-else-if="editorMode === 'visual'" v-model="content" :slug="slug" />
|
<VisualEditor v-else-if="editorMode === 'visual'" v-model="content" :slug="slug" :editable="canEditDoc" />
|
||||||
<SourceEditor v-else v-model="content" />
|
<SourceEditor v-else v-model="content" :readonly="!canEditDoc" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user