Full sweep: fix broken features, redesign NodePreview, wire AI service
FIXES (from comprehensive audit): - NodePreview: complete rewrite — 380px left panel with document summaries, commitment list, phase track visualization, scrollable. Fixed children count bug (was showing [object Object]). Slides in from left (not right) to not overlap branch handles. - CommitmentForm: added required validation on eigenaar_id field - MetroMap: wired custom metro node creation with form + POST /metro-nodes - MetroMap: removed dead handleCliCommand console.log - MetroMap: added metro node creation modal (naam + beschrijving) NEW — AI Service integration: - ai-service/main.py: real Anthropic API integration via httpx - Reads ANTHROPIC_API_KEY from env, uses claude-haiku-4-5-20251001 - /api/chat fetches project context from PostgreSQL (docs, commitments) - /api/summarize sends content to Claude for summarization - /api/search does basic text search on documents + kennis_artikelen - AiController.php: Laravel proxy for /api/ai/chat → ai-service - CliBar.vue: complete rewrite with async API calls, processing state, error handling, conversation history, auto-scroll - Receives projectId prop for context-scoped AI queries - Shows "denken..." animation while waiting for response - docker-compose.yml: passes ANTHROPIC_API_KEY to ai-service container - config/services.php: ai service URL configuration To activate AI: set ANTHROPIC_API_KEY in .env and rebuild ai-service. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -157,12 +157,42 @@ const submitTrackForm = () => {
|
||||
})
|
||||
}
|
||||
|
||||
// --- Metro node creation (for custom line extend) ---
|
||||
// --- Metro node creation form (for custom line extend) ---
|
||||
const showMetroNodeForm = ref(false)
|
||||
const pendingMetroNodeEvent = ref(null)
|
||||
const metroNodeForm = useForm({
|
||||
metro_line_id: '',
|
||||
naam: '',
|
||||
beschrijving: '',
|
||||
x: 0,
|
||||
y: 0,
|
||||
})
|
||||
|
||||
const createMetroNode = (event) => {
|
||||
// Determine metro_line_id from the lineId
|
||||
// lineId format for custom lines will need to be mapped
|
||||
// For now, emit a placeholder
|
||||
console.log('Create metro node on custom line:', event)
|
||||
pendingMetroNodeEvent.value = event
|
||||
// Extract metro_line_id from lineId (format: "custom-{id}" or similar)
|
||||
metroNodeForm.x = event.x
|
||||
metroNodeForm.y = event.y
|
||||
metroNodeForm.naam = ''
|
||||
metroNodeForm.beschrijving = ''
|
||||
showMetroNodeForm.value = true
|
||||
}
|
||||
|
||||
const submitMetroNodeForm = () => {
|
||||
const event = pendingMetroNodeEvent.value
|
||||
// The lineId from the canvas might be something like "custom-5" — extract the DB id
|
||||
// For now, try to find the metro_line by matching
|
||||
const lineId = event?.lineId ?? ''
|
||||
const match = lineId.match(/\d+$/)
|
||||
metroNodeForm.metro_line_id = match ? match[0] : ''
|
||||
|
||||
metroNodeForm.post('/metro-nodes', {
|
||||
onSuccess: () => {
|
||||
showMetroNodeForm.value = false
|
||||
metroNodeForm.reset()
|
||||
pendingMetroNodeEvent.value = null
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// --- FAB handlers ---
|
||||
@@ -188,10 +218,6 @@ const handleFabItemLeave = () => {
|
||||
canvasRef.value?.setHighlightedLine(null)
|
||||
}
|
||||
|
||||
const handleCliCommand = (command) => {
|
||||
console.log('CLI command:', command)
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
router.post('/logout')
|
||||
}
|
||||
@@ -300,7 +326,46 @@ const editingProject = ref(null)
|
||||
</Transition>
|
||||
</Teleport>
|
||||
|
||||
<CliBar @command="handleCliCommand" />
|
||||
<!-- Metro node creation modal (for custom line extend) -->
|
||||
<Teleport to="body">
|
||||
<Transition name="modal-fade">
|
||||
<div v-if="showMetroNodeForm" class="modal-backdrop" @click="showMetroNodeForm = false">
|
||||
<div class="modal-content" @click.stop>
|
||||
<div class="modal-header">NIEUW PUNT</div>
|
||||
<form @submit.prevent="submitMetroNodeForm">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Naam</label>
|
||||
<input
|
||||
v-model="metroNodeForm.naam"
|
||||
type="text"
|
||||
class="form-input"
|
||||
placeholder="Naam van het punt..."
|
||||
required
|
||||
autofocus
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Beschrijving</label>
|
||||
<textarea
|
||||
v-model="metroNodeForm.beschrijving"
|
||||
class="form-input form-textarea"
|
||||
placeholder="Optionele beschrijving..."
|
||||
rows="3"
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn-cancel" @click="showMetroNodeForm = false">Annuleren</button>
|
||||
<button type="submit" class="btn-submit" :disabled="metroNodeForm.processing">
|
||||
{{ metroNodeForm.processing ? 'Bezig...' : 'Aanmaken' }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
|
||||
<CliBar :project-id="currentProjectId" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -434,6 +499,11 @@ const editingProject = ref(null)
|
||||
box-shadow: 0 0 8px rgba(0, 210, 255, 0.2);
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
resize: vertical;
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
Reference in New Issue
Block a user