All files / src/utils templates.ts

84.12% Statements 53/63
77.27% Branches 17/22
80% Functions 8/10
85% Lines 51/60

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 1281x 1x 1x 1x 1x 1x 1x                   1x 7x 7x   7x 13x 12x 12x       7x     7x 7x   7x   7x 7x   7x 7x           7x   7x 7x   7x 10x     7x     1x 7x 7x   7x 2x 2x     5x   5x 12x     12x 7x   5x   12x     5x                   5x           5x   5x   5x 2x       3x 3x   3x             1x                        
import joplin from "api";
import { getAllNotesInFolder } from "./folders";
import { getAllNotesWithTag, getAllTagsWithTitle } from "./tags";
import { TemplatesSourceSetting, TemplatesSource } from "../settings/templatesSource";
import { LocaleGlobalSetting } from "../settings/global";
import { encode, decode } from "html-entities";
import { AUTO_FOCUS_SCRIPT } from "./dialogHelpers";
 
export interface Note {
    id: string;
    title: string;
    body: string;
}
 
type NoteProperty = "body" | "id" | "title";
 
const removeDuplicateTemplates = (templates: Note[]) => {
    const uniqueTemplates: Note[] = [];
    const templateIds: string[] = [];
 
    templates.forEach(note => {
        if (!templateIds.includes(note.id)) {
            templateIds.push(note.id);
            uniqueTemplates.push(note);
        }
    });
 
    return uniqueTemplates;
}
 
const getAllTemplates = async () => {
    let templates: Note[] = [];
 
    const templatesSource = await TemplatesSourceSetting.get();
 
    if (templatesSource == TemplatesSource.Tag) {
        const templateTags = await getAllTagsWithTitle("template");
 
        for (const tag of templateTags) {
            templates = templates.concat(await getAllNotesWithTag(tag.id));
        }
    } else E{
        templates = templates.concat(await getAllNotesInFolder("Templates"));
    }
 
    templates = removeDuplicateTemplates(templates);
 
    let userLocale: string = await LocaleGlobalSetting.get();
    userLocale = userLocale.split("_").join("-");
 
    templates.sort((a, b) => {
        return a.title.localeCompare(b.title, [userLocale, "en-US"], { sensitivity: "accent", numeric: true });
    });
 
    return templates;
}
 
export async function getUserTemplateSelection(dialogHandle: string, property?: NoteProperty, promptLabel = "Template:"): Promise<string | null> {
    try {
        const templates = await getAllTemplates();
        
        if (templates.length === 0) {
            await joplin.views.dialogs.showMessageBox("No templates found! Please create a template and try again.");
            return null;
        }
 
        await joplin.views.dialogs.addScript(dialogHandle, "./views/webview.css");
 
        const optionsHtml = templates
            .filter(note => note && note.id && note.title)
            .map(note => {
                let optionValue;
                if (!property) {
                    optionValue = JSON.stringify(note);
                } else {
                    optionValue = note[property];
                }
                return `<option value="${encode(optionValue)}">${encode(note.title)}</option>`;
            }).join("");
 
        await joplin.views.dialogs.setHtml(dialogHandle, `
            <h2>${encode(promptLabel)}</h2>
            <form class="variablesForm" name="templates-form">
                <div class="variableName">Select a template:</div>
                <select name="template" id="autofocus-target">${optionsHtml}</select>
            </form>
            ${AUTO_FOCUS_SCRIPT}
        `);
 
        // Add buttons to the dialog
        await joplin.views.dialogs.setButtons(dialogHandle, [
            { id: "ok", title: "Select" },
            { id: "cancel", title: "Cancel" }
        ]);
 
        // Make dialog size adapt to content
        await joplin.views.dialogs.setFitToContent(dialogHandle, true);
 
        const result = await joplin.views.dialogs.open(dialogHandle);
        
        if (result.id === "cancel") {
            return null;
        }
        
        // Get the template value and decode HTML entities
        const templateValue = result.formData?.["templates-form"]?.template;
        const decodedValue = templateValue ? decode(templateValue) : null;
        
        return decodedValue;
    } catch (error) {
        console.error("Error in getUserTemplateSelection:", error);
        return null;
    }
}
 
export const getTemplateFromId = async (templateId: string | null): Promise<Note | null> => {
    Iif (!templateId) {
        return null;
    }
 
    try {
        return await joplin.data.get([ "notes", templateId ], { fields: ["id", "title", "body"] });
    } catch (error) {
        console.error("There was an error loading a template from id", error);
        return null;
    }
}