Skip to content

Commit

Permalink
fix: creation of unique note name
Browse files Browse the repository at this point in the history
  • Loading branch information
danielo515 committed Dec 16, 2023
1 parent 37e4508 commit cea1643
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 66 deletions.
9 changes: 6 additions & 3 deletions src/core/formDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from "./formDefinitionSchema";
import { A, O, pipe } from "@std";
import { ParsedTemplate } from "./template/templateParser";
import { Simplify } from "type-fest";
//=========== Types derived from schemas
type selectFromNotes = Output<typeof SelectFromNotesSchema>;
type inputSlider = Output<typeof InputSliderSchema>;
Expand Down Expand Up @@ -72,7 +73,9 @@ export type FieldDefinition = Output<typeof FieldDefinitionSchema>;
* FormDefinition is an already valid form, ready to be used in the form modal.
*/
export type FormDefinition = Output<typeof FormDefinitionLatestSchema>;
export type FormWithTemplate = FormDefinition & { template: ParsedTemplate }
export type FormWithTemplate = Simplify<
FormDefinition & Required<Pick<FormDefinition, "template">>
>;

export type FormOptions = {
values?: Record<string, unknown>;
Expand All @@ -81,8 +84,8 @@ export type FormOptions = {
type KeyOfUnion<T> = T extends unknown ? keyof T : never;
type PickUnion<T, K extends KeyOfUnion<T>> = T extends unknown
? K & keyof T extends never
? never
: Pick<T, K & keyof T>
? never
: Pick<T, K & keyof T>
: never;

export type AllSources = PickUnion<inputType, "source">["source"];
Expand Down
177 changes: 114 additions & 63 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,62 @@ import { EDIT_FORM_VIEW, EditFormView } from "src/views/EditFormView";
import { MANAGE_FORMS_VIEW, ManageFormsView } from "src/views/ManageFormsView";
import { ModalFormError } from "src/utils/ModalFormError";
import { FormWithTemplate, type FormDefinition } from "src/core/formDefinition";
import { formNeedsMigration, migrateToLatest, MigrationError, InvalidData } from "./core/formDefinitionSchema";
import { parseSettings, type ModalFormSettings, type OpenPosition, getDefaultSettings } from "src/core/settings";
import {
formNeedsMigration,
migrateToLatest,
MigrationError,
InvalidData,
} from "./core/formDefinitionSchema";
import {
parseSettings,
type ModalFormSettings,
type OpenPosition,
getDefaultSettings,
} from "src/core/settings";
import { 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 * as A from "fp-ts/Array";
import { settingsStore } from "./store/store";
import { O } from "@std";
import { executeTemplate } from "./core/template/templateParser";
import { NewNoteModal } from "./suggesters/NewNoteModal";
import { file_exists } from "./utils/files";
import { number } from "valibot";

type ViewType = typeof EDIT_FORM_VIEW | typeof MANAGE_FORMS_VIEW;

// Define functions and properties you want to make available to other plugins, or templater templates, etc
interface PublicAPI {
exampleForm(): Promise<FormResult>;
openForm(formReference: string | FormDefinition): Promise<FormResult>
openForm(formReference: string | FormDefinition): Promise<FormResult>;
}

function notifyParsingErrors(errors: InvalidData[]) {
if (errors.length === 0) { return }
log_notice('Some forms could not be parsed',
if (errors.length === 0) {
return;
}
log_notice(
"Some forms could not be parsed",
`We found some invalid data while parsing the form settings, please take a look at the following errors:
${errors.join('\n')}`
)
${errors.join("\n")}`,
);
}

function notifyMigrationErrors(errors: MigrationError[]) {
if (errors.length === 0) { return }
log_notice('Some forms could not be migrated',
if (errors.length === 0) {
return;
}
log_notice(
"Some forms could not be migrated",
`We tried to perform an automatic migration, but we failed. Go to the forms manager and fix the following forms:
${errors.map((e) => e.name).join('\n')}`
)
${errors.map((e) => e.name).join("\n")}`,
);
}
// 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 @@ -59,7 +76,7 @@ export default class ModalFormPlugin extends Plugin {

/**
* Opens the form in the editor.
* @returns
* @returns
*/
async editForm(formName: string) {
// By reading settings from the disk we get a copy of the form
Expand All @@ -68,16 +85,17 @@ 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`)
throw new ModalFormError(`Form ${formName} not found`);
}
if (formDefinition instanceof MigrationError) {
notifyMigrationErrors([formDefinition])
return
notifyMigrationErrors([formDefinition]);
return;
}
await this.activateView(EDIT_FORM_VIEW, formDefinition);

}

closeEditForm() {
Expand All @@ -90,29 +108,31 @@ 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") {
leaf = this.app.workspace.getLeaf('tab')
console.info("found leaf, no reason to create a new one");
} 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);
} else if (this.settings?.editorPosition === "left") {
leaf = this.app.workspace.getLeftLeaf(false);
} else if (this.settings?.editorPosition === "modal") {
leaf = this.app.workspace.getLeaf(false)
leaf = this.app.workspace.getLeaf(false);
} else {
leaf = this.app.workspace.getRightLeaf(false)
leaf = this.app.workspace.getRightLeaf(false);
}

await leaf.setViewState({
type: viewType,
active: true,
state,
});
this.app.workspace.revealLeaf(
leaf
);
this.app.workspace.revealLeaf(leaf);
return leaf;
}

Expand All @@ -123,18 +143,24 @@ 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, formDefinitions }
return [migrationIsNeeded, validSettings]
const validSettings: ModalFormSettings = {
...settings,
formDefinitions,
};
return [migrationIsNeeded, validSettings];
}),
E.getOrElse(() => [false, getDefaultSettings()])
)
E.getOrElse(() => [false, getDefaultSettings()]),
);

if (migrationIsNeeded) {
await this.saveSettings(settings);
console.info('Settings were migrated to the latest version')
console.info("Settings were migrated to the latest version");
}
return settings;
}
Expand All @@ -155,22 +181,24 @@ export default class ModalFormPlugin extends Plugin {
}
settingsStore.set(settings);
this.unsubscribeSettingsStore = settingsStore.subscribe((s) => {
console.log('settings changed', s)
console.log("settings changed", s);
this.settings = s;
this.saveSettings(s)
this.saveSettings(s);
});
this.api = new API(this.app, this);
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) => {
this.manageForms()
}
);
this.addRibbonIcon("documents", "Edit forms", (evt: MouseEvent) => {
this.manageForms();
});

this.addCommand({
id: "new-form",
Expand All @@ -187,12 +215,12 @@ export default class ModalFormPlugin extends Plugin {
},
});
this.addCommand({
id: 'create-note-from-form',
name: 'Create new note from a form',
id: "create-note-from-form",
name: "Create new note from a form",
callback: () => {
this.createNoteFromForm();
}
})
},
});

// This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new ModalFormSettingTab(this.app, this));
Expand All @@ -205,11 +233,19 @@ 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')
let destinationPath = `${destinationFolder || defaultNotesFolder.path}/${name}.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`;
}
let destinationPath = makePath(name, destinationFolder);
let i = 1;
while (file_exists(destinationPath, this.app)) {
destinationPath = `${defaultNotesFolder.path}/${name}-${i}.md`
destinationPath = makePath(name, destinationFolder, i);
i++;
}
return destinationPath;
Expand All @@ -231,17 +267,32 @@ export default class ModalFormPlugin extends Plugin {
return O.some(form as FormWithTemplate);
}
return O.none;
})
)
const onFormSelected = async (form: FormWithTemplate, noteName: string, destinationFolder: string) => {
}),
);
const onFormSelected = async (
form: FormWithTemplate,
noteName: string,
destinationFolder: string,
) => {
const formData = await this.api.openForm(form);
const newNoteFullPath = this.getUniqueNoteName(noteName, destinationFolder);
this.app.vault.create(newNoteFullPath, executeTemplate(form.template, formData.getData()))
}
const picker = new NewNoteModal(this.app, formsWithTemplates, ({ form, folder, noteName }) => {
onFormSelected(form, noteName, folder)
});
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);
};
const picker = new NewNoteModal(
this.app,
formsWithTemplates,
({ form, folder, noteName }) => {
onFormSelected(form, noteName, folder);
},
);
picker.open();
}

}

0 comments on commit cea1643

Please sign in to comment.