Add plugin platform with modular backend and frontend registry.
Split graph/import/meta into Django apps, add API v1 with OpenAPI and pytest, and introduce plugin registry with the tags reference plugin on both FE and BE. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -21,6 +21,17 @@
|
||||
:active-values="activeFilters"
|
||||
@toggle="toggleFilter"
|
||||
/>
|
||||
<div v-if="graphToolbarActions.length" class="graph-plugin-actions">
|
||||
<button
|
||||
v-for="action in graphToolbarActions"
|
||||
:key="action.id"
|
||||
type="button"
|
||||
class="btn btn-secondary btn-sm"
|
||||
@click="runGraphToolbarAction(action)"
|
||||
>
|
||||
{{ action.label }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="graph-area" ref="graphArea">
|
||||
@@ -150,7 +161,7 @@
|
||||
defineOptions({ name: 'Graph' })
|
||||
|
||||
import { ref, computed, onMounted, onUnmounted, onActivated, onDeactivated, nextTick, watch } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { RouterLink, useRouter } from 'vue-router'
|
||||
import { Network, DataSet } from 'vis-network/standalone'
|
||||
import { useContactsStore } from '../stores/contacts'
|
||||
import { useCtrlLinkSelection } from '../composables/useCtrlLinkSelection'
|
||||
@@ -168,6 +179,7 @@ import GraphNodeContextMenu from '../components/GraphNodeContextMenu.vue'
|
||||
import GraphEdgeContextMenu from '../components/GraphEdgeContextMenu.vue'
|
||||
import EditRelationModal from '../components/EditRelationModal.vue'
|
||||
import { useGraphNodeContextMenu } from '../composables/useGraphNodeContextMenu.js'
|
||||
import { getGraphToolbarActions } from '../core/pluginRegistry'
|
||||
|
||||
let themeObserver = null
|
||||
let detachContextHandler = null
|
||||
@@ -191,6 +203,8 @@ function openNodeInfo(node) {
|
||||
}
|
||||
|
||||
const store = useContactsStore()
|
||||
const router = useRouter()
|
||||
const graphToolbarActions = getGraphToolbarActions()
|
||||
const graphArea = ref(null)
|
||||
const graphContainer = ref(null)
|
||||
const loading = ref(true)
|
||||
@@ -774,6 +788,10 @@ function toggleChrome() {
|
||||
nextTick(() => network.value?.redraw())
|
||||
}
|
||||
|
||||
function runGraphToolbarAction(action) {
|
||||
action.onClick?.({ router })
|
||||
}
|
||||
|
||||
watch(() => store.dataRevision, async (revision) => {
|
||||
if (!network.value || revision === syncedRevision) return
|
||||
await applyGraphDataFromStore()
|
||||
@@ -832,6 +850,11 @@ onUnmounted(() => {
|
||||
flex-shrink: 0;
|
||||
padding: 0 28px 10px;
|
||||
}
|
||||
.graph-plugin-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.graph-chrome-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
Reference in New Issue
Block a user