ItemView that displays all forms with mode badges (C/U), click to open, settings gear button, and empty state. Uses SidebarPluginRef interface to avoid circular dependency with main.ts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
94 lines
2.4 KiB
TypeScript
94 lines
2.4 KiB
TypeScript
import { ItemView, WorkspaceLeaf, setIcon } from 'obsidian';
|
|
import { FormStore } from '../core/form-store';
|
|
|
|
export const VIEW_TYPE_FORMFIRE_SIDEBAR = 'formfire-sidebar';
|
|
|
|
/**
|
|
* Interface for the subset of FormfirePlugin that the sidebar needs.
|
|
* Avoids circular dependency with main.ts.
|
|
*/
|
|
export interface SidebarPluginRef {
|
|
store: FormStore;
|
|
openForm: (id: string) => void;
|
|
}
|
|
|
|
export class FormfireSidebarView extends ItemView {
|
|
private pluginRef: SidebarPluginRef;
|
|
|
|
constructor(leaf: WorkspaceLeaf, pluginRef: SidebarPluginRef) {
|
|
super(leaf);
|
|
this.pluginRef = pluginRef;
|
|
}
|
|
|
|
getViewType(): string {
|
|
return VIEW_TYPE_FORMFIRE_SIDEBAR;
|
|
}
|
|
|
|
getDisplayText(): string {
|
|
return 'Formfire';
|
|
}
|
|
|
|
getIcon(): string {
|
|
return 'file-input';
|
|
}
|
|
|
|
async onOpen(): Promise<void> {
|
|
this.render();
|
|
}
|
|
|
|
async onClose(): Promise<void> {
|
|
this.contentEl.empty();
|
|
}
|
|
|
|
public render(): void {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
|
|
const container = contentEl.createDiv({ cls: 'ff-sidebar' });
|
|
|
|
// Header
|
|
const header = container.createDiv({ cls: 'ff-sidebar-header' });
|
|
header.createSpan({ text: 'Forms', cls: 'ff-sidebar-title' });
|
|
|
|
const settingsBtn = header.createDiv({ cls: 'ff-sidebar-settings' });
|
|
setIcon(settingsBtn, 'settings');
|
|
settingsBtn.setAttribute('aria-label', 'Formfire settings');
|
|
settingsBtn.addEventListener('click', () => {
|
|
// Open Obsidian settings and navigate to the Formfire tab
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const appAny = this.app as any;
|
|
appAny.setting.open();
|
|
appAny.setting.openTabById('formfire');
|
|
});
|
|
|
|
// Form list
|
|
const forms = this.pluginRef.store.getAll();
|
|
|
|
if (forms.length === 0) {
|
|
container.createDiv({
|
|
cls: 'ff-sidebar-empty',
|
|
text: 'No forms yet. Open settings to create one.',
|
|
});
|
|
return;
|
|
}
|
|
|
|
const listEl = container.createDiv({ cls: 'ff-sidebar-list' });
|
|
|
|
for (const form of forms) {
|
|
const item = listEl.createDiv({ cls: 'ff-sidebar-item' });
|
|
|
|
const badgeCls =
|
|
form.mode === 'create' ? 'ff-badge-create' : 'ff-badge-update';
|
|
item.createSpan({
|
|
cls: `ff-sidebar-badge ${badgeCls}`,
|
|
text: form.mode === 'create' ? 'C' : 'U',
|
|
});
|
|
|
|
item.createSpan({ cls: 'ff-sidebar-name', text: form.name });
|
|
|
|
item.addEventListener('click', () => {
|
|
this.pluginRef.openForm(form.id);
|
|
});
|
|
}
|
|
}
|
|
}
|