Major additions accumulated over 9 days — single commit per request. Flow editor (new): - Generic visual editor for step trees, usable by project wizard + agent flows - PROJECT_KINDS / AGENT_KINDS catalogs decouple UI from domain - Drag-and-drop reorder via vuedraggable with scope isolation per peer group - Chain-aware depends_on rewrite on reorder (sequential only — DAGs preserved) - Variable picker with per-applies_to catalog (Customer / Quotation / Service Contract / Issue / Subscription), insert + copy-clipboard modes - trigger_condition helper with domain-specific JSONLogic examples - Global FlowEditorDialog mounted once in MainLayout, Odoo inline pattern - Server: targo-hub flow-runtime.js, flow-api.js, flow-templates.js - ERPNext: Flow Template/Run doctypes, scheduler, 5 seeded system templates - depends_on chips resolve to step labels instead of opaque "s4" ids QR/OCR scanner (field app): - Camera capture → Gemini Vision via targo-hub with 8s timeout - IndexedDB offline queue retries photos when signal returns - Watcher merges late-arriving scan results into the live UI Dispatch: - Planning mode (draft → publish) with offer pool for unassigned jobs - Shared presets, recurrence selector, suggested-slots dialog - PublishScheduleModal, unassign confirmation Ops app: - ClientDetailPage composables extraction (useClientData, useDeviceStatus, useWifiDiagnostic, useModemDiagnostic) - Project wizard: shared detail sections, wizard catalog/publish composables - Address pricing composable + pricing-mock data - Settings redesign hosting flow templates Targo-hub: - Contract acceptance (JWT residential + DocuSeal commercial tracks) - Referral system - Modem-bridge diagnostic normalizer - Device extractors consolidated Migration scripts: - Invoice/quote print format setup, Jinja rendering - Additional import + fix scripts (reversals, dates, customers, payments) Docs: - Consolidated: old scattered MDs → HANDOFF, ARCHITECTURE, DATA_AND_FLOWS, FLOW_EDITOR_ARCHITECTURE, BILLING_AND_PAYMENTS, CPE_MANAGEMENT, APP_DESIGN_GUIDELINES - Archived legacy wizard PHP for reference - STATUS snapshots for 2026-04-18/19 Cleanup: - Removed ~40 generated PDFs/HTMLs (invoice_preview*, rendered_jinja*) - .gitignore now covers invoice preview output + nested .DS_Store Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
71 lines
2.4 KiB
Vue
71 lines
2.4 KiB
Vue
<!--
|
|
FlowQuickButton.vue — Drop-in trigger button for the global Flow Editor.
|
|
|
|
Odoo-style "inline create from anywhere": any page includes this single
|
|
component and gets a consistent, contextually-loaded Flow editor popup.
|
|
|
|
Behavior:
|
|
- If `templateName` prop is set → opens existing template in edit mode
|
|
- Else → opens new-template wizard, pre-filling category / applies_to
|
|
/ trigger_event based on the page's context
|
|
|
|
Props:
|
|
- templateName string | null — if set, edit this FT
|
|
- label string — button label (default: "Flows")
|
|
- icon string — material icon name
|
|
- color string — Quasar colour token
|
|
- category string — preset for a new template
|
|
- appliesTo string — preset for a new template
|
|
- triggerEvent string — preset for a new template
|
|
- flat, dense, size … — passthrough to q-btn
|
|
|
|
Usage:
|
|
<FlowQuickButton category="residential" applies-to="Service Contract"
|
|
trigger-event="on_contract_signed" />
|
|
|
|
<FlowQuickButton template-name="FT-00005" label="Éditer onboarding" />
|
|
-->
|
|
<template>
|
|
<q-btn :flat="flat" :dense="dense" :size="size"
|
|
:color="color" :icon="icon" :label="label" no-caps
|
|
@click="onClick">
|
|
<q-tooltip v-if="tooltip">{{ tooltip }}</q-tooltip>
|
|
</q-btn>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { useFlowEditor } from 'src/composables/useFlowEditor'
|
|
|
|
const props = defineProps({
|
|
templateName: { type: String, default: null },
|
|
label: { type: String, default: 'Flows' },
|
|
icon: { type: String, default: 'account_tree' },
|
|
color: { type: String, default: 'indigo-6' },
|
|
tooltip: { type: String, default: '' },
|
|
flat: { type: Boolean, default: false },
|
|
dense: { type: Boolean, default: true },
|
|
size: { type: String, default: 'md' },
|
|
category: { type: String, default: 'other' },
|
|
appliesTo: { type: String, default: null },
|
|
triggerEvent: { type: String, default: null },
|
|
})
|
|
|
|
const emit = defineEmits(['saved'])
|
|
|
|
const fe = useFlowEditor()
|
|
|
|
function onClick () {
|
|
const onSaved = (tpl) => emit('saved', tpl)
|
|
if (props.templateName) {
|
|
fe.openTemplate(props.templateName, { onSaved })
|
|
} else {
|
|
fe.openNew({
|
|
category: props.category,
|
|
applies_to: props.appliesTo,
|
|
trigger_event: props.triggerEvent,
|
|
onSaved,
|
|
})
|
|
}
|
|
}
|
|
</script>
|