import { App, Plugin, PluginSettingTab, Setting, Notice } from 'obsidian'; import { FormStore } from '../core/form-store'; import { FormBuilderModal } from './form-builder'; import { exportForms, importForms } from '../utils/form-io'; /** * Interface for the subset of FormfirePlugin that the settings tab needs. * Avoids circular dependency with main.ts. */ export interface SettingsPluginRef extends Plugin { store: FormStore; saveSettings: () => Promise; refreshSidebar: () => void; } /** * Formfire settings tab — lists all forms with Edit / Duplicate / Delete, * plus a button to create new forms. */ export class FormfireSettingTab extends PluginSettingTab { private pluginRef: SettingsPluginRef; constructor(app: App, plugin: SettingsPluginRef) { super(app, plugin); this.pluginRef = plugin; } display(): void { const { containerEl } = this; containerEl.empty(); containerEl.createEl('h2', { text: 'Formfire' }); // New form button new Setting(containerEl) .setName('Create a new form') .setDesc('Add a new form definition to your collection.') .addButton((btn) => { btn.setButtonText('+ New Form').setCta().onClick(() => { const blank = this.pluginRef.store.createBlank(); new FormBuilderModal(this.app, blank, async (saved) => { this.pluginRef.store.add(saved); await this.pluginRef.saveSettings(); this.pluginRef.refreshSidebar(); this.display(); }).open(); }); }); // Import / Export new Setting(containerEl) .setName('Import / Export') .setDesc('Share forms as JSON files.') .addButton((btn) => { btn.setButtonText('Export All').onClick(() => { const forms = this.pluginRef.store.getAll(); if (forms.length === 0) { new Notice('No forms to export.'); return; } const json = exportForms(forms); const blob = new Blob([json], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'formfire-export.json'; a.click(); URL.revokeObjectURL(url); }); }) .addButton((btn) => { btn.setButtonText('Import').onClick(() => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'; input.addEventListener('change', async () => { const file = input.files?.[0]; if (!file) return; try { const text = await file.text(); const forms = importForms(text); for (const form of forms) { this.pluginRef.store.add(form); } await this.pluginRef.saveSettings(); this.pluginRef.refreshSidebar(); this.display(); new Notice(`Imported ${forms.length} form(s).`); } catch (err) { new Notice( err instanceof Error ? err.message : 'Import failed.', ); } }); input.click(); }); }); // Form list const forms = this.pluginRef.store.getAll(); if (forms.length === 0) { containerEl.createDiv({ cls: 'ff-settings-empty', text: 'No forms defined yet. Click the button above to create your first form.', }); return; } containerEl.createEl('h3', { text: 'Your Forms' }); for (const form of forms) { const modeDesc = form.mode === 'create' ? `Creates notes in ${form.targetFolder ?? '/'}` : `Updates ${form.targetFile === 'active' ? 'active file' : 'prompted file'}`; const fieldCount = form.fields.length; const desc = `${modeDesc} \u2022 ${fieldCount} field${fieldCount !== 1 ? 's' : ''}`; new Setting(containerEl) .setName(form.name) .setDesc(desc) .addButton((btn) => { btn.setButtonText('Export').onClick(() => { const json = exportForms([form]); const blob = new Blob([json], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `formfire-${form.name.toLowerCase().replace(/\s+/g, '-')}.json`; a.click(); URL.revokeObjectURL(url); }); }) .addButton((btn) => { btn.setButtonText('Edit').onClick(() => { new FormBuilderModal(this.app, form, async (saved) => { this.pluginRef.store.update(form.id, saved); await this.pluginRef.saveSettings(); this.pluginRef.refreshSidebar(); this.display(); }).open(); }); }) .addButton((btn) => { btn.setButtonText('Duplicate').onClick(async () => { this.pluginRef.store.duplicate(form.id); await this.pluginRef.saveSettings(); this.pluginRef.refreshSidebar(); this.display(); new Notice(`Duplicated "${form.name}".`); }); }) .addButton((btn) => { btn .setButtonText('Delete') .setWarning() .onClick(async () => { this.pluginRef.store.remove(form.id); await this.pluginRef.saveSettings(); this.pluginRef.refreshSidebar(); this.display(); new Notice(`Deleted "${form.name}".`); }); }); } } }