85 lines
3.3 KiB
Python
85 lines
3.3 KiB
Python
from django.core.management.base import BaseCommand
|
|
import yaml
|
|
import os
|
|
import json
|
|
from django.conf import settings
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = "Generate IntroJS tour definitions from workflow documentation"
|
|
|
|
def handle(self, *args, **kwargs):
|
|
input_file = "haikal_kb.yaml"
|
|
output_dir = os.path.join(settings.BASE_DIR, 'static', 'js', 'tours')
|
|
|
|
# Create output directory if it doesn't exist
|
|
os.makedirs(output_dir, exist_ok=True)
|
|
|
|
try:
|
|
with open(input_file, 'r', encoding='utf-8') as f:
|
|
kb = yaml.safe_load(f)
|
|
except Exception as e:
|
|
self.stdout.write(self.style.ERROR(f"Error reading knowledge base file: {e}"))
|
|
return
|
|
|
|
workflows = kb.get("user_workflows", {})
|
|
|
|
tours_created = 0
|
|
|
|
# Map of common UI elements to their likely selectors
|
|
element_selectors = {
|
|
"inventory": "#inventory-menu, .inventory-nav, nav .inventory",
|
|
"add car": "#add-car-button, .btn-add-car, button:contains('Add Car')",
|
|
"save": "button[type='submit'], .btn-save, #save-button",
|
|
"cancel": ".btn-cancel, #cancel-button, button:contains('Cancel')",
|
|
"vin": "#vin-input, input[name='vin'], .vin-field",
|
|
"make": "#make-select, select[name='make'], .make-field",
|
|
"model": "#model-select, select[name='model'], .model-field",
|
|
"series": "#series-select, select[name='series'], .series-field",
|
|
"trim": "#trim-select, select[name='trim'], .trim-field",
|
|
"price": "#price-input, input[name='price'], .price-field",
|
|
"color": "#color-select, select[name='color'], .color-field",
|
|
"invoice": "#invoice-section, .invoice-tab, #create-invoice",
|
|
"customer": "#customer-select, select[name='customer'], .customer-field",
|
|
"finance": "#finance-menu, .finance-nav, nav .finance",
|
|
}
|
|
|
|
for workflow_name, workflow in workflows.items():
|
|
steps = workflow.get("steps", [])
|
|
if not steps:
|
|
continue
|
|
|
|
tour_steps = []
|
|
|
|
for i, step in enumerate(steps):
|
|
# Try to identify UI element from step description
|
|
element = None
|
|
for key, selector in element_selectors.items():
|
|
if key.lower() in step.lower():
|
|
element = selector
|
|
break
|
|
|
|
tour_step = {
|
|
"title": f"Step {i + 1}",
|
|
"intro": step,
|
|
"position": "bottom"
|
|
}
|
|
|
|
if element:
|
|
tour_step["element"] = element
|
|
|
|
tour_steps.append(tour_step)
|
|
|
|
# Save the tour definition as JSON
|
|
tour_filename = workflow_name.lower().replace(' ', '_') + '_tour.json'
|
|
with open(os.path.join(output_dir, tour_filename), 'w', encoding='utf-8') as f:
|
|
json.dump({
|
|
"name": workflow_name,
|
|
"description": workflow.get("description", ""),
|
|
"steps": tour_steps
|
|
}, f, indent=2)
|
|
|
|
tours_created += 1
|
|
|
|
self.stdout.write(self.style.SUCCESS(f"✅ Created {tours_created} IntroJS tour definitions in {output_dir}"))
|