feat: add sidebar view with form list
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>
This commit is contained in:
parent
092c960a9c
commit
5eb79fbf08
1 changed files with 94 additions and 0 deletions
94
src/ui/form-sidebar.ts
Normal file
94
src/ui/form-sidebar.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue