Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/edit form command #201

Merged
merged 4 commits into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 10 additions & 21 deletions src/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import ModalFormPlugin from "./main";
import { ModalFormError } from "./utils/ModalFormError";
import { FormModal } from "./FormModal";
import { log_error, log_notice } from "./utils/Log";
import * as std from "@std";

type pickOption = { pick: string[] };
type omitOption = { omit: string[] };
Expand All @@ -21,6 +22,7 @@ function isOmitOption(opts: limitOptions): opts is omitOption {
}

export class API {
std = std;
/**
* Constructor for the API class
* @param {App} app - The application instance
Expand All @@ -29,17 +31,14 @@ export class API {
constructor(
private app: App,
private plugin: ModalFormPlugin,
) { }
) {}

/**
* Opens a modal form with the provided form definition
* @param {FormDefinition} formDefinition - The form definition to use
* @returns {Promise<FormResult>} - A promise that resolves with the form result
*/
openModalForm(
formDefinition: FormDefinition,
options?: FormOptions,
): Promise<FormResult> {
openModalForm(formDefinition: FormDefinition, options?: FormOptions): Promise<FormResult> {
return new Promise((resolve) => {
new FormModal(this.app, formDefinition, resolve, options).open();
});
Expand All @@ -49,14 +48,12 @@ export class API {
}

private getFormByName(name: string): FormDefinition | undefined {
const form = this.plugin.settings?.formDefinitions.find(
(form) => form.name === name,
);
const form = this.plugin.settings?.formDefinitions.find((form) => form.name === name);
if (form instanceof MigrationError) {
log_notice(
"🚫 The form you tried to load has an invalid format",
`The form "${name}" has an invalid format.` +
`We tried to automatically convert it but it failed, please fix it manually in the forms manager.
`We tried to automatically convert it but it failed, please fix it manually in the forms manager.
`,
);
return undefined;
Expand All @@ -76,9 +73,7 @@ export class API {
if (formDefinition) {
return this.openModalForm(formDefinition, options);
} else {
const error = new ModalFormError(
`Form definition ${name} not found`,
);
const error = new ModalFormError(`Form definition ${name} not found`);
log_error(error);
return Promise.reject(error);
}
Expand All @@ -92,16 +87,12 @@ export class API {
const omit = opts.omit;
newFormDefinition = {
...formDefinition,
fields: formDefinition.fields.filter(
(field) => !omit.includes(field.name),
),
fields: formDefinition.fields.filter((field) => !omit.includes(field.name)),
};
} else if (isPickOption(opts)) {
newFormDefinition = {
...formDefinition,
fields: formDefinition.fields.filter((field) =>
opts.pick.includes(field.name),
),
fields: formDefinition.fields.filter((field) => opts.pick.includes(field.name)),
};
} else {
throw new ModalFormError(
Expand All @@ -111,9 +102,7 @@ export class API {
}
return this.openModalForm(newFormDefinition);
} else {
const error = new ModalFormError(
`Form definition ${name} not found`,
);
const error = new ModalFormError(`Form definition ${name} not found`);
log_error(error);
return Promise.reject(error);
}
Expand Down
2 changes: 1 addition & 1 deletion src/FormModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class FormModal extends Modal {
const name = definition.label || definition.name;
const required = definition.isRequired ?? false;
const fieldBase = new Setting(contentEl)
.setName(`${name} ${required ? "*" : ""}`)
.setName(`${name} ${required ? "*" : ""}`.trim())
.setDesc(definition.description);
// This intermediary constants are necessary so typescript can narrow down the proper types.
// without them, you will have to use the whole access path (definition.input.folder),
Expand Down
78 changes: 35 additions & 43 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,12 @@ import {
getDefaultSettings,
} from "src/core/settings";
import { log_error, log_notice } from "./utils/Log";
import * as E from "fp-ts/Either";
import { pipe } from "fp-ts/function";
import * as A from "fp-ts/Array";
import { settingsStore } from "./store/store";
import { O } from "@std";
import { O, pipe, E, A } from "@std";
import { executeTemplate } from "./core/template/templateParser";
import { NewNoteModal } from "./suggesters/NewNoteModal";
import { file_exists } from "./utils/files";
import { FormPickerModal } from "./suggesters/FormPickerModal";

type ViewType = typeof EDIT_FORM_VIEW | typeof MANAGE_FORMS_VIEW;

Expand Down Expand Up @@ -61,7 +59,7 @@ function notifyMigrationErrors(errors: MigrationError[]) {
// This is the plugin entrypoint
export default class ModalFormPlugin extends Plugin {
public settings: ModalFormSettings | undefined;
private unsubscribeSettingsStore: () => void = () => { };
private unsubscribeSettingsStore: () => void = () => {};
// This things will be setup in the onload function rather than constructor
public api!: PublicAPI;

Expand All @@ -84,9 +82,7 @@ export default class ModalFormPlugin extends Plugin {
// then if you save another form you will unexpectedly save the mutated form too.
// Maybe we could instead do a deep copy instead, but until this proven to be a bottleneck I will leave it like this.
const savedSettings = await this.getSettings();
const formDefinition = savedSettings.formDefinitions.find(
(form) => form.name === formName,
);
const formDefinition = savedSettings.formDefinitions.find((form) => form.name === formName);
if (!formDefinition) {
throw new ModalFormError(`Form ${formName} not found`);
}
Expand All @@ -107,14 +103,10 @@ export default class ModalFormPlugin extends Plugin {

async activateView(viewType: ViewType, state?: FormDefinition) {
const { workspace } = this.app;
let leaf: WorkspaceLeaf | undefined =
workspace.getLeavesOfType(viewType)[0];
let leaf: WorkspaceLeaf | undefined = workspace.getLeavesOfType(viewType)[0];
if (leaf) {
console.info("found leaf, no reason to create a new one");
} else if (
Platform.isMobile ||
this.settings?.editorPosition === "mainView"
) {
} else if (Platform.isMobile || this.settings?.editorPosition === "mainView") {
leaf = this.app.workspace.getLeaf("tab");
} else if (this.settings?.editorPosition === "right") {
leaf = this.app.workspace.getRightLeaf(false);
Expand Down Expand Up @@ -142,11 +134,10 @@ export default class ModalFormPlugin extends Plugin {
const [migrationIsNeeded, settings] = pipe(
parseSettings(data),
E.map((settings): [boolean, ModalFormSettings] => {
const migrationIsNeeded =
settings.formDefinitions.some(formNeedsMigration);
const { right: formDefinitions, left: errors } = A.partitionMap(
migrateToLatest,
)(settings.formDefinitions);
const migrationIsNeeded = settings.formDefinitions.some(formNeedsMigration);
const { right: formDefinitions, left: errors } = A.partitionMap(migrateToLatest)(
settings.formDefinitions,
);
notifyParsingErrors(errors);
const validSettings: ModalFormSettings = {
...settings,
Expand Down Expand Up @@ -175,8 +166,8 @@ export default class ModalFormPlugin extends Plugin {

attachShortcutToGlobalWindow() {
if (!this.settings) {
log_error(new ModalFormError("Settings not loaded yet"))
return
log_error(new ModalFormError("Settings not loaded yet"));
return;
}
const globalNamespace = this.settings.globalNamespace;
if (this.settings?.attachShortcutToGlobalWindow) {
Expand All @@ -190,6 +181,13 @@ export default class ModalFormPlugin extends Plugin {
await this.saveSettings();
}

get validFormDefinitions(): FormDefinition[] {
return pipe(
this.settings!.formDefinitions,
A.filterMap((form) => (form instanceof MigrationError ? O.none : O.some(form))),
);
}

async onload() {
const settings = await this.getSettings();
if (settings.formDefinitions.length === 0) {
Expand All @@ -203,14 +201,8 @@ export default class ModalFormPlugin extends Plugin {
});
this.api = new API(this.app, this);
this.attachShortcutToGlobalWindow();
this.registerView(
EDIT_FORM_VIEW,
(leaf) => new EditFormView(leaf, this),
);
this.registerView(
MANAGE_FORMS_VIEW,
(leaf) => new ManageFormsView(leaf, this),
);
this.registerView(EDIT_FORM_VIEW, (leaf) => new EditFormView(leaf, this));
this.registerView(MANAGE_FORMS_VIEW, (leaf) => new ManageFormsView(leaf, this));

// This creates an icon in the left ribbon.
this.addRibbonIcon("documents", "Edit forms", (evt: MouseEvent) => {
Expand Down Expand Up @@ -239,6 +231,16 @@ export default class ModalFormPlugin extends Plugin {
},
});

this.addCommand({
id: "edit-form",
name: "Edit form",
callback: async () => {
new FormPickerModal(this.app, this.validFormDefinitions, (formToEdit) => {
this.activateView(EDIT_FORM_VIEW, formToEdit);
}).open();
},
});

// This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new ModalFormSettingTab(this.app, this));
}
Expand All @@ -250,13 +252,9 @@ export default class ModalFormPlugin extends Plugin {
* @returns a unique name for the note, full path including the extension
*/
getUniqueNoteName(name: string, destinationFolder?: string): string {
const defaultNotesFolder = this.app.fileManager.getNewFileParent(
"",
"note.md",
);
const defaultNotesFolder = this.app.fileManager.getNewFileParent("", "note.md");
function makePath(name: string, folder?: string, suffix?: number) {
return `${folder || defaultNotesFolder.path}/${name}${suffix ? "-" + suffix : ""
}.md`;
return `${folder || defaultNotesFolder.path}/${name}${suffix ? "-" + suffix : ""}.md`;
}
let destinationPath = makePath(name, destinationFolder);
let i = 1;
Expand Down Expand Up @@ -291,14 +289,8 @@ export default class ModalFormPlugin extends Plugin {
destinationFolder: string,
) => {
const formData = await this.api.openForm(form);
const newNoteFullPath = this.getUniqueNoteName(
noteName,
destinationFolder,
);
const noteContent = executeTemplate(
form.template.parsedTemplate,
formData.getData(),
);
const newNoteFullPath = this.getUniqueNoteName(noteName, destinationFolder);
const noteContent = executeTemplate(form.template.parsedTemplate, formData.getData());
console.log("new note content", noteContent);
this.app.vault.create(newNoteFullPath, noteContent);
};
Expand Down