update
This commit is contained in:
@@ -5,13 +5,18 @@ Darkmode
|
|||||||
optional
|
optional
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
<!-- ziel -->
|
<!-- ziel -->
|
||||||
|
Zwischen Tag- und Nachtmodus wechseln
|
||||||
|
----------------------------------------
|
||||||
|
<!-- regeln -->
|
||||||
|
- Standard sind die Systemeinstellungen
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
<!-- funktion -->
|
<!-- funktion -->
|
||||||
Darkmode umschalten
|
Darkmode umschalten
|
||||||
<!-- regeln -->
|
<!-- regeln -->
|
||||||
- Icon: ☾ / ☀
|
- Nacht-Icon: ☾
|
||||||
- Folgt beim ersten Start der System-Einstellung
|
- Tag-Icon: ☀
|
||||||
|
- Auto-Icon: A
|
||||||
- Zustand bleibt gespeichert
|
- Zustand bleibt gespeichert
|
||||||
<!-- testen -->
|
<!-- testen -->
|
||||||
- Klick auf Icon in der Sidebar oben
|
- LMB auf Icon in der Sidebar oben
|
||||||
|
- Modus schaltet weiter: Auto, Tag, Nacht
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Features
|
|||||||
kern
|
kern
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
<!-- ziel -->
|
<!-- ziel -->
|
||||||
Gruppieren Informationen zu ähnlichen Funktionen
|
Gruppiert Informationen zu ähnlichen Funktionen
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
<!-- regeln -->
|
<!-- regeln -->
|
||||||
- Alphabetisch sortiert
|
- Alphabetisch sortiert
|
||||||
@@ -16,21 +16,21 @@ Gruppieren Informationen zu ähnlichen Funktionen
|
|||||||
<!-- funktion -->
|
<!-- funktion -->
|
||||||
Anzeigemodus umschalten
|
Anzeigemodus umschalten
|
||||||
<!-- ziel -->
|
<!-- ziel -->
|
||||||
Kompaktmodus zum lesen und Vollmodus zum vertiefen und anpassen
|
Kompaktmodus zum Lesen und Vollmodus zum Vertiefen und Anpassen
|
||||||
<!-- regeln -->
|
<!-- regeln -->
|
||||||
- Standard ist Kompaktmodus
|
- Standard ist Kompaktmodus
|
||||||
- Vollmodus geht über responsive Spalten
|
- Vollmodus geht über responsive Spalten
|
||||||
- Vollmodus zeigt alles
|
- Vollmodus zeigt alles
|
||||||
- Kompaktmodus zeigt Ziel und Funktionstitel als Liste
|
- Kompaktmodus zeigt Ziel und Funktionstitel als Liste
|
||||||
|
- Augen-Icon rechts oben
|
||||||
<!-- testen -->
|
<!-- testen -->
|
||||||
- Klick auf Karte
|
- MMB auf Karte
|
||||||
- Vollmodus sichtbar
|
- Modus der Karte wechselt
|
||||||
- Klick auf freie Kartenfläche
|
- Alternativ Klick auf Augen-Icon
|
||||||
- Kompaktmodus sichtbar
|
|
||||||
<!-- funktion -->
|
<!-- funktion -->
|
||||||
Badge umschalten
|
Badge umschalten
|
||||||
<!-- ziel -->
|
<!-- ziel -->
|
||||||
Unterscheidet die Kern- und Optionalen Features
|
Unterscheidet die Kern- und optionalen Features
|
||||||
<!-- regeln -->
|
<!-- regeln -->
|
||||||
- Kernfarbe blau
|
- Kernfarbe blau
|
||||||
- Optionalfarbe grün
|
- Optionalfarbe grün
|
||||||
|
|||||||
@@ -5,49 +5,74 @@ Funktionen
|
|||||||
kern
|
kern
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
<!-- ziel -->
|
<!-- ziel -->
|
||||||
|
Konkrete Funktionen zum Feature
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
<!-- funktion -->
|
|
||||||
Testen anpassen
|
|
||||||
<!-- regeln -->
|
<!-- regeln -->
|
||||||
- Ein Testen-Block je Funktion
|
- Alphabetisch sortiert
|
||||||
- Leeren entfernt den Block
|
- Anpassen nur im Vollmodus
|
||||||
<!-- testen -->
|
- Verlassen speichert
|
||||||
- Klick auf Testen oder + Testen
|
- Escape verwirft
|
||||||
- Inhalt anpassen
|
----------------------------------------
|
||||||
<!-- funktion -->
|
|
||||||
Funktion anpassen
|
|
||||||
<!-- testen -->
|
|
||||||
- Klick auf Text
|
|
||||||
- Inhalt ändern
|
|
||||||
<!-- funktion -->
|
<!-- funktion -->
|
||||||
Funktion entfernen
|
Funktion entfernen
|
||||||
<!-- regeln -->
|
<!-- regeln -->
|
||||||
- Feld leeren entfernt auch
|
- x-Icon
|
||||||
<!-- testen -->
|
<!-- testen -->
|
||||||
- Hover über Funktion
|
- Vollmodus öffnen
|
||||||
- Klick auf x
|
- RMB auf Funktion
|
||||||
|
- Klick auf "Funktion entfernen"
|
||||||
|
- Bestätigen im Modal
|
||||||
|
- Funktion entfernt
|
||||||
<!-- funktion -->
|
<!-- funktion -->
|
||||||
Funktion hinzufügen
|
Funktion erstellen
|
||||||
<!-- regeln -->
|
<!-- regeln -->
|
||||||
- Alphabetisch sortiert
|
- +-Icon
|
||||||
- Neue Funktion rückt nach dem Speichern an ihre Position
|
|
||||||
<!-- testen -->
|
<!-- testen -->
|
||||||
- Klick auf + Funktion
|
- Vollmodus öffnen
|
||||||
- Inhalt eingeben
|
- RMB auf Featurecard
|
||||||
<!-- funktion -->
|
- Klick auf "Funktion erstellen"
|
||||||
Ziel anpassen
|
- Namen im Modal eingeben
|
||||||
<!-- regeln -->
|
- Bestätigen
|
||||||
- Ein Ziel je Funktion
|
|
||||||
- Leeren entfernt das Ziel
|
|
||||||
<!-- testen -->
|
|
||||||
- Klick auf Ziel oder + Ziel
|
|
||||||
- Inhalt anpassen
|
|
||||||
<!-- funktion -->
|
<!-- funktion -->
|
||||||
Regeln anpassen
|
Regeln anpassen
|
||||||
|
<!-- ziel -->
|
||||||
|
Spezifische Hinweise für die Funktion
|
||||||
<!-- regeln -->
|
<!-- regeln -->
|
||||||
- Eine Regel je Zeile
|
- Eine Regel je Zeile
|
||||||
- Leeren entfernt alle Regeln
|
- Jeweils nur 1 kompakter Satz
|
||||||
<!-- testen -->
|
<!-- testen -->
|
||||||
- Klick auf Regeln oder + Regeln
|
- Vollmodus öffnen
|
||||||
|
- Klick auf Regeln der Funktion
|
||||||
|
- Inhalt anpassen
|
||||||
|
<!-- funktion -->
|
||||||
|
Testen anpassen
|
||||||
|
<!-- ziel -->
|
||||||
|
Beschreibt die Schritte zum Prüfen der Funktion
|
||||||
|
<!-- regeln -->
|
||||||
|
- Ein Schritt je Zeile
|
||||||
|
- Jeweils nur 1 kompakter Satz
|
||||||
|
<!-- testen -->
|
||||||
|
- Vollmodus öffnen
|
||||||
|
- Klick auf Testen der Funktion
|
||||||
|
- Inhalt anpassen
|
||||||
|
<!-- funktion -->
|
||||||
|
Titel anpassen
|
||||||
|
<!-- ziel -->
|
||||||
|
Beschreibt die Funktion so kompakt wie möglich
|
||||||
|
<!-- regeln -->
|
||||||
|
- Nur wenige Wörter
|
||||||
|
<!-- testen -->
|
||||||
|
- Vollmodus öffnen
|
||||||
|
- Klick auf Titel der Funktion
|
||||||
|
- Inhalt anpassen
|
||||||
|
<!-- funktion -->
|
||||||
|
Ziel anpassen
|
||||||
|
<!-- ziel -->
|
||||||
|
Beschreibt kurz das Kernziel der Funktion
|
||||||
|
<!-- regeln -->
|
||||||
|
- 1-2 simple Sätze
|
||||||
|
- Nur wenn der Titel nicht selbsterklärend ist
|
||||||
|
<!-- testen -->
|
||||||
|
- Vollmodus öffnen
|
||||||
|
- Klick auf Ziel der Funktion
|
||||||
- Inhalt anpassen
|
- Inhalt anpassen
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ Gruppiert Features für ein Projekt
|
|||||||
- Alphabetisch sortiert
|
- Alphabetisch sortiert
|
||||||
- Aktives Projekt ist hervorgehoben
|
- Aktives Projekt ist hervorgehoben
|
||||||
- 1-2 Wörter für den Namen
|
- 1-2 Wörter für den Namen
|
||||||
|
- Verlassen speichert
|
||||||
|
- Escape verwirft
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
<!-- funktion -->
|
<!-- funktion -->
|
||||||
Projekt anpassen
|
Projekt anpassen
|
||||||
@@ -30,7 +32,7 @@ Projekt aufrufen
|
|||||||
<!-- funktion -->
|
<!-- funktion -->
|
||||||
Projekt entfernen
|
Projekt entfernen
|
||||||
<!-- regeln -->
|
<!-- regeln -->
|
||||||
- X-Icon
|
- x-Icon
|
||||||
- Auch Features entfernen
|
- Auch Features entfernen
|
||||||
<!-- testen -->
|
<!-- testen -->
|
||||||
- RMB auf Projektname
|
- RMB auf Projektname
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { nextTick, onMounted, ref, watch } from 'vue'
|
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import { marked } from 'marked'
|
import { marked } from 'marked'
|
||||||
import { featureSpeichern } from '../api.js'
|
import { featureSpeichern } from '../api.js'
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ const props = defineProps({
|
|||||||
feature: { type: Object, required: true },
|
feature: { type: Object, required: true },
|
||||||
vollmodus: { type: Boolean, default: false }, // frisch angelegt: direkt im Vollmodus öffnen
|
vollmodus: { type: Boolean, default: false }, // frisch angelegt: direkt im Vollmodus öffnen
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['aktualisiert', 'kontextmenue'])
|
const emit = defineEmits(['aktualisiert', 'entfernen'])
|
||||||
|
|
||||||
function kopie(sekt) {
|
function kopie(sekt) {
|
||||||
return {
|
return {
|
||||||
@@ -71,7 +71,6 @@ function abbrechen() {
|
|||||||
async function fertig() {
|
async function fertig() {
|
||||||
const a = aktiv.value
|
const a = aktiv.value
|
||||||
if (!a) return
|
if (!a) return
|
||||||
blurZeit = Date.now() // der Klick, der das Feld schloss, soll die Ansicht nicht schließen
|
|
||||||
aktiv.value = null
|
aktiv.value = null
|
||||||
const neu = entwurf.value.trim()
|
const neu = entwurf.value.trim()
|
||||||
|
|
||||||
@@ -99,14 +98,56 @@ function abbrechenLeer(a) {
|
|||||||
if (!a.original && a.feld === 'funktion') s.value.funktionen.splice(a.i, 1)
|
if (!a.original && a.feld === 'funktion') s.value.funktionen.splice(a.i, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
function neueFunktion() {
|
// Kontextmenü: RMB auf eine Funktion (entfernen) oder auf die Karte (erstellen/Feature entfernen)
|
||||||
s.value.funktionen.unshift({ text: '', ziel: '', regeln: '', testen: '' })
|
const kontextMenue = ref(null) // {funktion: index|null, x, y}
|
||||||
starte('funktion', 0)
|
|
||||||
|
function oeffneKontextMenue(e, i = null) {
|
||||||
|
kontextMenue.value = { funktion: i, x: e.clientX, y: e.clientY }
|
||||||
}
|
}
|
||||||
|
|
||||||
function entferneFunktion(i) {
|
function schliesseKontextMenue() {
|
||||||
s.value.funktionen.splice(i, 1)
|
kontextMenue.value = null
|
||||||
speichern()
|
}
|
||||||
|
|
||||||
|
onMounted(() => window.addEventListener('click', schliesseKontextMenue))
|
||||||
|
onUnmounted(() => window.removeEventListener('click', schliesseKontextMenue))
|
||||||
|
|
||||||
|
// Modal für Funktion erstellen und entfernen
|
||||||
|
const modal = ref(null) // {art: 'erstellen'} | {art: 'entfernen', i}
|
||||||
|
const modalName = ref('')
|
||||||
|
const modalFeld = ref(null)
|
||||||
|
|
||||||
|
async function menueFunktionErstellen() {
|
||||||
|
kontextMenue.value = null
|
||||||
|
modal.value = { art: 'erstellen' }
|
||||||
|
modalName.value = ''
|
||||||
|
await nextTick()
|
||||||
|
modalFeld.value?.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
function menueFunktionEntfernen() {
|
||||||
|
const i = kontextMenue.value.funktion
|
||||||
|
kontextMenue.value = null
|
||||||
|
modal.value = { art: 'entfernen', i }
|
||||||
|
}
|
||||||
|
|
||||||
|
function menueFeatureEntfernen() {
|
||||||
|
kontextMenue.value = null
|
||||||
|
emit('entfernen')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function erstellenBestaetigen() {
|
||||||
|
const name = modalName.value.trim()
|
||||||
|
if (!name) return
|
||||||
|
s.value.funktionen.push({ text: name, ziel: '', regeln: '', testen: '' })
|
||||||
|
modal.value = null
|
||||||
|
await speichern()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function entfernenBestaetigen() {
|
||||||
|
s.value.funktionen.splice(modal.value.i, 1)
|
||||||
|
modal.value = null
|
||||||
|
await speichern()
|
||||||
}
|
}
|
||||||
|
|
||||||
function wechsleArt() {
|
function wechsleArt() {
|
||||||
@@ -157,20 +198,10 @@ function punkte(text) {
|
|||||||
return text.split('\n').map(z => z.replace(/^[-*]\s*/, '').trim()).filter(Boolean)
|
return text.split('\n').map(z => z.replace(/^[-*]\s*/, '').trim()).filter(Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standardansicht ist reine Übersicht: Klick öffnet die ausführliche Ansicht,
|
// Kompaktmodus zum Lesen, Vollmodus zum Anpassen — MMB auf die Karte
|
||||||
// nur dort wird bearbeitet; Klick auf freie Fläche schließt sie wieder —
|
// oder das Augen-Icon schaltet um
|
||||||
// außer der Klick hat gerade eine Bearbeitung beendet (Blur kommt vor dem Klick)
|
function wechsleAnsicht() {
|
||||||
let blurZeit = 0
|
gross.value = !gross.value
|
||||||
|
|
||||||
function wechsleAnsicht(e) {
|
|
||||||
if (gross.value) {
|
|
||||||
if (e.target.closest('button, input, textarea, .klickbar, h3, .hinweis')) return
|
|
||||||
if (Date.now() - blurZeit < 300) return
|
|
||||||
gross.value = false
|
|
||||||
} else {
|
|
||||||
if (e.target.closest('button, input, textarea')) return
|
|
||||||
gross.value = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -182,8 +213,9 @@ onMounted(() => {
|
|||||||
<article
|
<article
|
||||||
class="karte"
|
class="karte"
|
||||||
:class="[s.art, { gross }]"
|
:class="[s.art, { gross }]"
|
||||||
@click="wechsleAnsicht"
|
@mousedown.middle.prevent
|
||||||
@contextmenu.prevent.stop="emit('kontextmenue', $event)"
|
@auxclick.middle.prevent="wechsleAnsicht"
|
||||||
|
@contextmenu.prevent.stop="oeffneKontextMenue($event)"
|
||||||
>
|
>
|
||||||
<header>
|
<header>
|
||||||
<input
|
<input
|
||||||
@@ -204,6 +236,11 @@ onMounted(() => {
|
|||||||
@click="wechsleArt"
|
@click="wechsleArt"
|
||||||
>{{ s.art }}</button>
|
>{{ s.art }}</button>
|
||||||
<span v-else class="badge" :class="s.art === 'kern' ? 'blau' : 'gruen'">{{ s.art }}</span>
|
<span v-else class="badge" :class="s.art === 'kern' ? 'blau' : 'gruen'">{{ s.art }}</span>
|
||||||
|
<button
|
||||||
|
class="icon-knopf"
|
||||||
|
:title="gross ? 'Kompaktmodus' : 'Vollmodus'"
|
||||||
|
@click="wechsleAnsicht"
|
||||||
|
>👁</button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section :class="{ leer: !s.ziel && !istAktiv('ziel') }">
|
<section :class="{ leer: !s.ziel && !istAktiv('ziel') }">
|
||||||
@@ -239,13 +276,13 @@ onMounted(() => {
|
|||||||
|
|
||||||
<section :class="{ leer: !s.funktionen.length }">
|
<section :class="{ leer: !s.funktionen.length }">
|
||||||
<p class="gruppe">Funktionen</p>
|
<p class="gruppe">Funktionen</p>
|
||||||
<button v-if="gross" class="hinzu werkzeug" @click="neueFunktion">+ Funktion</button>
|
|
||||||
<div class="liste">
|
<div class="liste">
|
||||||
<div
|
<div
|
||||||
v-for="(f, i) in s.funktionen"
|
v-for="(f, i) in s.funktionen"
|
||||||
:key="i"
|
:key="i"
|
||||||
class="funktion"
|
class="funktion"
|
||||||
:class="{ offen: aktiv && aktiv.i === i }"
|
:class="{ offen: aktiv && aktiv.i === i }"
|
||||||
|
@contextmenu.prevent.stop="oeffneKontextMenue($event, i)"
|
||||||
>
|
>
|
||||||
<div class="zeile kopf">
|
<div class="zeile kopf">
|
||||||
<span class="pfeil">▸</span>
|
<span class="pfeil">▸</span>
|
||||||
@@ -258,7 +295,6 @@ onMounted(() => {
|
|||||||
@keydown.esc="abbrechen"
|
@keydown.esc="abbrechen"
|
||||||
>
|
>
|
||||||
<div v-else class="funktionstitel klickbar" @click="starte('funktion', i)">{{ f.text }}</div>
|
<div v-else class="funktionstitel klickbar" @click="starte('funktion', i)">{{ f.text }}</div>
|
||||||
<button v-if="gross" class="icon-knopf rot" title="Funktion entfernen" @click="entferneFunktion(i)">✕</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Regeln und Flow nur beim Hover über die Funktion (oder während der Bearbeitung) -->
|
<!-- Regeln und Flow nur beim Hover über die Funktion (oder während der Bearbeitung) -->
|
||||||
@@ -320,11 +356,49 @@ onMounted(() => {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<p v-if="meldung" class="meldung">{{ meldung }}</p>
|
<p v-if="meldung" class="meldung">{{ meldung }}</p>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="kontextMenue"
|
||||||
|
class="kontextmenue"
|
||||||
|
:style="{ left: kontextMenue.x + 'px', top: kontextMenue.y + 'px' }"
|
||||||
|
>
|
||||||
|
<button v-if="kontextMenue.funktion !== null" @click="menueFunktionEntfernen">✕ Funktion entfernen</button>
|
||||||
|
<template v-else>
|
||||||
|
<button v-if="gross" @click="menueFunktionErstellen">+ Funktion erstellen</button>
|
||||||
|
<button @click="menueFeatureEntfernen">✕ Feature entfernen</button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="modal" class="schleier" @click.self="modal = null">
|
||||||
|
<div class="modal karte">
|
||||||
|
<template v-if="modal.art === 'erstellen'">
|
||||||
|
<h2>Funktion erstellen</h2>
|
||||||
|
<input
|
||||||
|
ref="modalFeld"
|
||||||
|
v-model="modalName"
|
||||||
|
placeholder="Funktionstitel"
|
||||||
|
@keyup.enter="erstellenBestaetigen"
|
||||||
|
@keydown.esc="modal = null"
|
||||||
|
>
|
||||||
|
<footer>
|
||||||
|
<button @click="modal = null">Abbrechen</button>
|
||||||
|
<button class="primaer" :disabled="!modalName.trim()" @click="erstellenBestaetigen">Bestätigen</button>
|
||||||
|
</footer>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<h2>Funktion entfernen</h2>
|
||||||
|
<p class="frage">„{{ s.funktionen[modal.i].text }}“ entfernen?</p>
|
||||||
|
<footer>
|
||||||
|
<button @click="modal = null">Abbrechen</button>
|
||||||
|
<button class="primaer" @click="entfernenBestaetigen">Entfernen</button>
|
||||||
|
</footer>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.karte { cursor: pointer; }
|
|
||||||
.karte.kern { border-color: var(--akzent); }
|
.karte.kern { border-color: var(--akzent); }
|
||||||
.karte.optional { border-color: var(--gruen); }
|
.karte.optional { border-color: var(--gruen); }
|
||||||
|
|
||||||
@@ -356,7 +430,7 @@ header {
|
|||||||
padding-bottom: 0.55rem;
|
padding-bottom: 0.55rem;
|
||||||
border-bottom: 1px solid var(--rand);
|
border-bottom: 1px solid var(--rand);
|
||||||
}
|
}
|
||||||
h3 { margin: 0; font-size: 1rem; cursor: pointer; flex: 1; }
|
h3 { margin: 0; font-size: 1rem; flex: 1; }
|
||||||
/* Im Bearbeitungsmodus zeigt Hover die klickbare Titelfläche */
|
/* Im Bearbeitungsmodus zeigt Hover die klickbare Titelfläche */
|
||||||
.karte.gross h3 {
|
.karte.gross h3 {
|
||||||
padding: 0.1rem 0.3rem;
|
padding: 0.1rem 0.3rem;
|
||||||
@@ -392,7 +466,7 @@ section.leer { display: none; }
|
|||||||
padding: 0.1rem 0.3rem;
|
padding: 0.1rem 0.3rem;
|
||||||
margin: 0.1rem 0 0.1rem -0.3rem;
|
margin: 0.1rem 0 0.1rem -0.3rem;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: text;
|
||||||
}
|
}
|
||||||
.hinweis:hover { background: var(--code-bg); }
|
.hinweis:hover { background: var(--code-bg); }
|
||||||
.hinzu {
|
.hinzu {
|
||||||
@@ -470,7 +544,10 @@ textarea {
|
|||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
.klickbar { cursor: pointer; user-select: none; }
|
/* Karte: MMB schaltet den Modus um; Texte sind nur im Vollmodus bearbeitbar */
|
||||||
|
.karte { cursor: pointer; }
|
||||||
|
.klickbar { user-select: none; }
|
||||||
|
.karte.gross .klickbar, .karte.gross h3 { cursor: text; }
|
||||||
.inhalt.klickbar { border-radius: 4px; }
|
.inhalt.klickbar { border-radius: 4px; }
|
||||||
.inhalt.klickbar:hover { background: var(--code-bg); }
|
.inhalt.klickbar:hover { background: var(--code-bg); }
|
||||||
h3, .hinweis { user-select: none; }
|
h3, .hinweis { user-select: none; }
|
||||||
|
|||||||
@@ -29,15 +29,11 @@ function aktualisiert(altId, f) {
|
|||||||
if (neuId.value === altId) neuId.value = f.id
|
if (neuId.value === altId) neuId.value = f.id
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kontextmenü: Rechtsklick auf eine Card (entfernen) oder den Hauptbereich (erstellen)
|
// Kontextmenü auf dem Hauptbereich (erstellen); das Menü der Card führt die Karte selbst
|
||||||
const kontextMenue = ref(null) // {feature|null, x, y}
|
const kontextMenue = ref(null) // {x, y}
|
||||||
|
|
||||||
function oeffneKartenMenue(e, f) {
|
|
||||||
kontextMenue.value = { feature: f, x: e.clientX, y: e.clientY }
|
|
||||||
}
|
|
||||||
|
|
||||||
function oeffneBereichsMenue(e) {
|
function oeffneBereichsMenue(e) {
|
||||||
kontextMenue.value = { feature: null, x: e.clientX, y: e.clientY }
|
kontextMenue.value = { x: e.clientX, y: e.clientY }
|
||||||
}
|
}
|
||||||
|
|
||||||
function schliesseKontextMenue() {
|
function schliesseKontextMenue() {
|
||||||
@@ -61,9 +57,7 @@ async function menueErstellen() {
|
|||||||
modalFeld.value?.focus()
|
modalFeld.value?.focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
function menueEntfernen() {
|
function featureEntfernen(feature) {
|
||||||
const feature = kontextMenue.value.feature
|
|
||||||
kontextMenue.value = null
|
|
||||||
meldung.value = ''
|
meldung.value = ''
|
||||||
modal.value = { art: 'entfernen', feature }
|
modal.value = { art: 'entfernen', feature }
|
||||||
}
|
}
|
||||||
@@ -110,7 +104,7 @@ watch(() => props.projekt, laden, { immediate: true })
|
|||||||
:feature="f"
|
:feature="f"
|
||||||
:vollmodus="f.id === neuId"
|
:vollmodus="f.id === neuId"
|
||||||
@aktualisiert="aktualisiert"
|
@aktualisiert="aktualisiert"
|
||||||
@kontextmenue="oeffneKartenMenue($event, f)"
|
@entfernen="featureEntfernen(f)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -119,8 +113,7 @@ watch(() => props.projekt, laden, { immediate: true })
|
|||||||
class="kontextmenue"
|
class="kontextmenue"
|
||||||
:style="{ left: kontextMenue.x + 'px', top: kontextMenue.y + 'px' }"
|
:style="{ left: kontextMenue.x + 'px', top: kontextMenue.y + 'px' }"
|
||||||
>
|
>
|
||||||
<button v-if="kontextMenue.feature" @click="menueEntfernen">✕ Feature entfernen</button>
|
<button @click="menueErstellen">+ Feature erstellen</button>
|
||||||
<button v-else @click="menueErstellen">+ Feature erstellen</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="modal" class="schleier" @click.self="modal = null">
|
<div v-if="modal" class="schleier" @click.self="modal = null">
|
||||||
|
|||||||
Reference in New Issue
Block a user