linkWelcome Note:

This plugin customizes a note by modifying its name, adding tags, and applying predefined settings based on user input, handling asynchronous interactions with the application API for seamless updates. It enhances note organization by allowing users to add multiple tags and emojis, making it easier to sort and filter notes based on various criteria such as status, priority, or type. The predefined options offer standardized formatting for users who frequently use similar tags or formats, streamlining the customization process.


The intuitive prompt-based interface and asynchronous updates ensure a user-friendly experience and efficient note management. Additionally, the plugin's flexibility and scalability make it adaptable to evolving user needs, providing a practical tool for advanced note organization and customization.


linkDemo:

linkGeneral - Calling the Plugin - Tagger Pro



linkGeneral - Calling the Plugin - Tagger Pro - "ctrl/cmd + o"




linkDocumentation:

This plugin allows users to customize their notes by modifying names, adding tags, and applying predefined settings. It interacts asynchronously with the application API to ensure smooth and responsive updates.

Customize Your Note:

The plugin will prompt you with options to customize the note:

Tags Selection: Choose up to 10 tags to add to the note.

Single Tag: Type a single tag to add to the note.

Emoji Selection: Pick an emoji to represent the note's status or type. Choose its position as either a prefix or suffix.

Predefined Options: Select a predefined sample for quick customization, which includes preset emojis and tags.

Complete Customization:

After providing your inputs, the plugin will:

Update the note’s name with the selected emoji.

Add the specified tags to the note.

Apply predefined settings if no other customization is selected.

>>>

Correlation Matrix for Tags:

This is based on a feature request - Link - Tag Analysis.

It gives you a report of comparative analysis using Correlation Matrix, It give you a count of occurrence two tags have occurred together.

You can get his in Document Report (Suggested), Document Report - Trend, CSV Table (Analysis), JSON, Matrix Downloadable formats.

Clickable Links for Groups:

This generates a new notes under the tag-reports/-tagger-pro, this gives you easy access to all the Group Filters that are available in Amplenote. Using the reference from Search queries: tag, filter, and other queries

Clickable Links for Tags:

This generates a new notes under the tag-reports/-tagger-pro, this gives you easy access to all the Tags that are available in your Amplenote. You can reorganize, copy and re-use them where-ever needed. It can help you out in your workflow.


linkTable - Plugin Parameters:

name

Tagger Pro

icon

label

description

Type {Tagger Pro} in any note to specify and apply a tag (Existing - up to 10, and Non Existing - up to 1), especially useful in Jots Mode where the tag button is hidden, and includes features like user prompts for tags, emoji selection, position selection, and note name modifications.
New in Pro: It had give you a Correlation Matrix for Tags, Clickable Links for Groups and Tags.

instructions

Please fine the Instructions here = Tagger Pro - Docs Tagger Pro - Docs 2
Old Version: Tagger 2.0

setting

Group_Clickable_Links_UUID [Do not Edit!]

setting

Tag_Clickable_Links_UUID [Do not Edit!]


linkCode Base:

{
/* ----------------------------------- */
// Define an asynchronous function 'noteOption' that takes 'app' and 'noteUUID' as parameters
async insertText(app, noteUUID) {
// Log the start of the function
// console.log("Starting insertText function");
 
// Find the note using the UUID
const note = await app.findNote({uuid: app.context.noteUUID});
// console.log("Note found:", note);
 
// ------- Display a prompt to customize the note -------
const result = await app.prompt("Customize your note", {
inputs: [
{
label: "Select the tags (Max 10) to add to the Note!",
type: "tags",
limit: 10
},
{
label: "Type a Tag to apply (Not Existing* / Existing) - (* - Preferred)",
placeholder: "Your tag here",
type: "string",
},
{
label: "Select emoji",
type: "select",
options: [
// Task Status
{ label: "Task Status: ✅ Completed", value: "✅" },
{ label: "Task Status: ⚠️ Important", value: "⚠️" },
{ label: "Task Status: 🔴 Urgent", value: "🔴" },
{ label: "Task Status: 🟡 Pending", value: "🟡" },
{ label: "Task Status: 🟢 Done", value: "🟢" },
{ label: "Task Status: ⏳ In Progress", value: "⏳" },
 
// Note Type
{ label: "Note Type: 📝 Note", value: "📝" },
{ label: "Note Type: 💡 Idea", value: "💡" },
{ label: "Note Type: 🔍 Review", value: "🔍" },
{ label: "Note Type: 📚 Research", value: "📚" },
 
// Priority
{ label: "Priority: 📌 Pinned", value: "📌" },
{ label: "Priority: 🔒 Confidential", value: "🔒" },
 
// Time Management
{ label: "Time Management: 📅 Scheduled", value: "📅" },
{ label: "Time Management: 🕒 Later", value: "🕒" },
 
// Work and Personal
{ label: "Work: 💼 Work", value: "💼" },
{ label: "Work: 🎓 Study", value: "🎓" },
{ label: "Personal: 🏠 Home", value: "🏠" },
{ label: "Personal: 🛒 Shopping", value: "🛒" },
{ label: "Personal: ✈️ Travel", value: "✈️" },
{ label: "Personal: 🎉 Event", value: "🎉" },
 
// Miscellaneous
{ label: "Miscellaneous: ⚙️ Settings", value: "⚙️" },
{ label: "Miscellaneous: 🌟 Highlight", value: "🌟" },
{ label: "Miscellaneous: 🎯 Goal", value: "🎯" },
{ label: "Miscellaneous: 🛠️ Maintenance", value: "🛠️" },
{ label: "Miscellaneous: 💬 Discussion", value: "💬" },
{ label: "Miscellaneous: 🚀 Launch", value: "🚀" }
]
},
{
label: "Select position",
type: "select",
options: [
{ label: "Prefix", value: "" }, // Set an empty value for Prefix
{ label: "Suffix", value: "suffix" }
]
},
{
label: "Predefined Options (Advanced - Check+Modify Code Based on your Specific Requirments)",
type: "select",
options: [
{ label: "Predefined Sample 1: Completed", value: "1" },
{ label: "Predefined Sample 2: Ideas", value: "2" },
{ label: "Predefined Sample 3: Travel Goals", value: "3" } // More Options can be added as per your Requirements!
]
}
]
});
 
// Log the result of the prompt
// console.log("Prompt result:", result);
 
// ------- Check if the user has cancelled the operation -------
if (!result) {
// console.log("User cancelled the operation");
app.alert("Operation has been cancelled. Tata! Bye Bye! Cya!");
return;
}
 
// ------- Destructure user inputs -------
const [multiTag, singleTag, emoji, position, predefined] = result;
// console.log("User inputs - multiTag:", multiTag, ", singleTag:", singleTag, ", emoji:", emoji, ", position:", position, ", predefined:", predefined);
 
// ------- Handle Note Name Modifications -------
if (emoji) {
//const noteHandle = await app.findNote({ uuid: noteUUID }); // Find the note using UUID
// console.log("Note handle found:", note);
 
let updatedName = note.name;
 
if (position === "suffix") {
updatedName = `${note.name} ${emoji}`; // Add emoji as suffix
// console.log("Updated name with prefix:", updatedName);
} else { // old version - //} else if (position === "suffix") {
updatedName = `${emoji} ${note.name}`; // Add emoji as prefix
// console.log("Updated name with suffix:", updatedName);
}
 
await app.setNoteName(note, updatedName); // Update the note name
// console.log("Note name updated to:", updatedName);
}
 
// ------- Add tags to the note if provided -------
if (multiTag) {
// Split the multiTag string by commas into an array of tags
const tagsArray = multiTag.split(',').map(tag => tag.trim()); // Trim spaces around each tag
 
// Log the separated tags
// console.log("Multiple tags to be added:", tagsArray);
 
// Add each tag to the note separately
for (const tag of tagsArray) {
if (tag) { // Ensure the tag is not empty
await app.addNoteTag({ uuid: app.context.noteUUID }, tag);
// console.log("Added tag:", tag);
}
}
 
//return null; // Return an empty string after adding tags
}
 
// ------- Add single tag preferably new to the note if provided -------
if (singleTag) {
await app.addNoteTag({ uuid: app.context.noteUUID }, singleTag);
// console.log("Single tag added:", singleTag);
//return null;
}
 
// ------- Handle Predefined Modifications -------
if (!singleTag && !multiTag && !emoji && !position) {
// const noteHandle = await app.findNote({ uuid: noteUUID }); // Find the note using UUID
// console.log("Note handle found:", note);
 
// Define variables outside of the conditional blocks
let prefixz;
let suffixz;
let multiTagsz;
let updatedNamez = note.name;
// console.log("updatedNamez:", updatedNamez);
 
if (predefined === "1") {
prefixz = "✅";
suffixz = "📝";
multiTagsz = "completed, reviewed";
}
else if (predefined === "2") {
prefixz = "💡";
multiTagsz = "ideabox, ideas, thinking";
}
else if (predefined === "3") {
prefixz = "🎯";
suffixz = "✈️";
multiTagsz = "travel, goals";
}
// More Options can be added as per your Requirements!
// Example usage of the variables
// console.log("Prefix:", prefixz);
// console.log("Suffix:", suffixz);
// console.log("Multi Tags:", multiTagsz);
 
updatedNamez = `${prefixz}${note.name}${suffixz}`; // Add emoji as prefix or suffix
await app.setNoteName(note, updatedNamez); // Update the note name
// console.log("Note name updated to:", updatedNamez);
 
// Split the multiTag string by commas into an array of tags
const tagsArrayz = multiTagsz.split(',').map(tagz => tagz.trim()); // Trim spaces around each tag
// console.log("Multiple tags to be added:", tagsArrayz);
 
// Add each tag to the note separately
for (const tagz of tagsArrayz) {
if (tagz) { // Ensure the tag is not empty
await app.addNoteTag({ uuid: app.context.noteUUID }, tagz);
// console.log("Added tag:", tagz);
}
}
 
}
 
return null; // Return an empty string after adding tags
},
/* ----------------------------------- */
appOption: {
/* ----------------------------------- */
"Correlation Count Matrix for Tags": async function (app) {
/* ----------------------------------- */
const result = await app.prompt("Select details for Correlation Matrix for Tags", {
inputs: [
{ label: "Select the Tags to Include in Report (leave blank to consider all)", type: "tags", limit: 10 },
{ label: "Select the Tags to Exclude in Report (leave blank to consider all)", type: "tags", limit: 10 },
{ label: "Format to Download", type: "radio",
options: [
{ label: "Document Report (Suggested)", value: "report" },
{ label: "Document Report - Trend", value: "trend" },
{ label: "CSV Table (Analysis)", value: "csv" },
{ label: "JSON", value: "json" },
{ label: "Matrix", value: "txt" }
]
},
]
});
 
// ------- Check if the user has cancelled the operation -------
if (!result) {
// console.log("User cancelled the operation");
app.alert("Operation has been cancelled. Tata! Bye Bye! Cya!");
return;
}
 
const [ tagNames, tagNamesEx, downloadType ] = result;
// console.log("result:",result);
const tagsArray = tagNames ? tagNames.split(',').map(tag => tag.trim()) : [];
// console.log("tagsArray:",tagsArray);
const tagsArrayEx = tagNamesEx ? tagNamesEx.split(',').map(tag => '^' + tag.trim()) : [];
// console.log("tagsArrayEx:",tagsArrayEx);
 
if (tagsArray.length > 0 && tagsArrayEx.length > 0) {
// console.log("User selected both include and exclude.");
app.alert("Choose either Include or Exclude.");
return;
}
 
let notes = [];
if (tagsArray.length > 0) {
for (let tag of tagsArray) {
let taggedNotes = await app.filterNotes({
tag
});
notes = notes.concat(taggedNotes);
}
} else if (tagsArrayEx.length > 0) {
for (let tag of tagsArrayEx) {
let taggedNotes = await app.filterNotes({
tag
});
notes = notes.concat(taggedNotes);
}
} else {
notes = await app.filterNotes({ });
}
// console.log("notes:",notes);
// Flatten the tags, remove duplicates, and sort the result
const noteTags = Array.from(new Set(notes.flatMap(note => note.tags))).sort();
// console.log("noteTags:",noteTags);
 
// Step 1: Extract the tags from each note and flatten them
const allTags = notes.map(note => note.tags);
 
// Step 2: Get the unique variables (tags)
const variables = Array.from(new Set(allTags.flat())).sort();
 
// Step 3: Initialize a matrix of zeros (for counting pairs)
const matrix = Array(variables.length).fill(0).map(() => Array(variables.length).fill(0));
 
// Step 4: Helper function to increment the count for a pair in the matrix
const incrementMatrix = (var1, var2) => {
const i = variables.indexOf(var1);
const j = variables.indexOf(var2);
if (i === j) {
matrix[i][i] += 1; // Only increment once if it's a self pair (same tag)
} else {
matrix[i][j] += 1;
matrix[j][i] += 1; // Increment both sides for different pairs (symmetrical)
}
};
 
// Step 5: Process each combination of tags
allTags.forEach(combo => {
if (combo.length === 1) {
// If the tag is alone, increment the count for the same tag (self pair)
incrementMatrix(combo[0], combo[0]);
} else {
// If there are multiple tags, increment counts for each pair
for (let i = 0; i < combo.length; i++) {
for (let j = i + 1; j < combo.length; j++) {
incrementMatrix(combo[i], combo[j]);
}
}
}
});
 
// Output the variables (unique tags) and the matrix
// console.log('Variables (Tags):', variables);
// console.log('Matrix:', matrix);
 
// Function to download content in specified format
const downloadFile = (data, fileName, type) => {
const blob = new Blob([data], { type });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
// console.log('download started.');
 
// Function to get current date and time formatted as YYMMDD_HHMMSS
function getCurrentDateTime() {
const now = new Date();
 
// Format the date and time as per requirement
const YYMMDD = now.toLocaleDateString('en-GB').split('/').reverse().join('');
const HHMMSS = now.toLocaleTimeString('en-GB', { hour12: false }).replace(/:/g, '');
 
return { YYMMDD, HHMMSS };
}
 
// Generate a new note with the results
const { YYMMDD, HHMMSS } = getCurrentDateTime();
 
// Function to generate text report excluding zero matches
const generateTextReport = () => {
let report = '';
 
variables.forEach((tag, i) => {
const matches = [];
matrix[i].forEach((count, j) => {
if (count > 0) {
matches.push(`${variables[j]}: ${count}`);
}
});
 
if (matches.length > 0) {
report += `- Tag: ${tag}\nMatch:\n${matches.join('\n')}\n\n`;
}
});
 
return report;
};
 
// Function to generate trend report showing highest match counts (excluding self-pairs)
const generateTrendReport = () => {
let trends = [];
 
// Collect all pairs and their match counts, but exclude self-pairs (e.g., a, a)
for (let i = 0; i < variables.length; i++) {
for (let j = i + 1; j < variables.length; j++) { // Start from i+1 to avoid self-pairs
if (matrix[i][j] > 0) {
trends.push({
pair: [variables[i], variables[j]],
count: matrix[i][j]
});
}
}
}
 
// Sort pairs by their match count in descending order
trends.sort((a, b) => b.count - a.count);
 
// Create the report in the desired format
let trendReport = 'Trend of highest match counts:\n\n';
trends.forEach((trend, index) => {
trendReport += `- ${index + 1} - ${trend.pair.join(', ')}: ${trend.count}\n`;
});
 
return trendReport;
};
 
// Generate file based on downloadType
const generateDownload = (downloadType) => {
let content = '';
const fileName = `notes.${downloadType}`;
 
if (downloadType === 'csv') {
// Generate CSV
const csvRows = ['Tags,\'' + variables.join(',\'')];
matrix.forEach((row, i) => {
csvRows.push('\'' + variables[i] + ',' + row.join(','));
});
content = csvRows.join('\n');
downloadFile(content, `Correlation count matrix (Tags CSV Table) ${YYMMDD}-${HHMMSS}.csv`, 'text/csv');
 
} else if (downloadType === 'json') {
// Generate JSON
const jsonObject = {
variables: variables,
matrix: matrix
};
content = JSON.stringify(jsonObject, null, 2);
downloadFile(content, `Correlation count matrix (Tags JSON) ${YYMMDD}-${HHMMSS}.json`, 'application/json');
 
} else if (downloadType === 'txt') {
// Generate Matrix text format (for Array)
const matrixRows = ['Matrix Representation:'];
matrix.forEach((row, i) => {
matrixRows.push(variables[i] + ' -> ' + row.join(' '));
});
content = matrixRows.join('\n');
downloadFile(content, `Correlation count matrix (Tags Matrix) ${YYMMDD}-${HHMMSS}.txt`, 'text/plain');
} else if (downloadType === 'report') {
// Generate the tag match report with non-zero counts
content = generateTextReport();
downloadFile(content, `Correlation count matrix (Tag Match Report) ${YYMMDD}-${HHMMSS}.txt`, 'text/plain');
} else if (downloadType === 'trend') {
// Generate the trend report of highest match counts
content = generateTrendReport();
downloadFile(content, `Correlation count matrix (Tag Match Trend) ${YYMMDD}-${HHMMSS}.txt`, 'text/plain');
} else {
// console.log('Invalid download type');
}
};
generateDownload(downloadType);
// console.log('Finished');
},
/* ----------------------------------- */
"Clickable Links for Groups": async function (app) {
/* ----------------------------------- */
// console.log('Groups (Clickable Links) Started');
const groupMarkdown = `
---
### Grouped-folders
- **[Archived](https://www.amplenote.com/notes?group=archived)**: Notes that have been archived or auto-archived.
- **[Vault Notes](https://www.amplenote.com/notes?group=vault)**: Encrypted notes.
- **[Deleted Notes](https://www.amplenote.com/notes?group=deleted)**: Notes that have been deleted in the past 30 days.
- **[Active plugin notes](https://www.amplenote.com/notes?group=plugin)**: Notes that represent currently active plugins.
### Notes-contain-tasks
- **[Task Lists](https://www.amplenote.com/notes?group=taskLists)**: Notes that contain tasks inside them.
### Notes-untagged
- **[Un-tagged](https://www.amplenote.com/notes?group=untagged)**: Notes that are not assigned any tag.
### Shared-notes
- **[Created by me](https://www.amplenote.com/notes?group=created)**: Notes that have been created by the current user.
- **[Shared publicly](https://www.amplenote.com/notes?group=public)**: Notes that have been published to the web via a public URL.
- **[Shared notes](https://www.amplenote.com/notes?group=shared)**: Notes created by anyone that are shared with at least another user.
- **[Notes shared with me](https://www.amplenote.com/notes?group=shareReceived)**: Notes that have been created by others but shared with the current user.
- **[Notes not created by me](https://www.amplenote.com/notes?group=notCreated)**: Notes that have been created by others but shared with the current user.
- **[Notes I shared with others](https://www.amplenote.com/notes?group=shareSent)**: Notes created by the current user and shared with others.
### Creation-date
- **[This week](https://www.amplenote.com/notes?group=thisWeek)**: Notes that have been created some time over the previous 7 days.
- **[Today](https://www.amplenote.com/notes?group=today)**: Notes that have been edited in the current day.
### Low-level-queries
- **[Notes Saving](https://www.amplenote.com/notes?group=saving)**: Notes that have pending changes to push to the server.
- **[Notes Downloading](https://www.amplenote.com/notes?group=stale)**: Notes that have pending changes to pull from the server.
- **[Notes Indexing](https://www.amplenote.com/notes?group=indexing)**: Notes that are currently being indexed for search locally.
---
### Details<!-- {"collapsed":true} -->
This Markdown format presents the data clearly, with **Categories** as headers and each option having a link and description.
**Options** first with **Markdown links**, followed by the **description**, and use **categories** as headers.
**For more details:** [Search queries: tag, filter, and other queries](https://www.amplenote.com/help/search_filter_tags_groups)
`;
 
// console.log("groupMarkdown:",groupMarkdown);
 
// Group Report
const groupNoteName = `Group Clickable Links`;
const groupTagName = ['-reports/-tagger-pro'];
const groupnoteUUID = await (async () => {
const existingUUID = await app.settings["Group_Clickable_Links_UUID [Do not Edit!]"];
if (existingUUID)
return existingUUID;
// console.log("existingUUID:",existingUUID);
const newUUID = await app.createNote(groupNoteName, groupTagName);
await app.setSetting("Group_Clickable_Links_UUID [Do not Edit!]", newUUID);
return newUUID;
// console.log("newUUID:",newUUID);
})();
// console.log("groupnoteUUID:",groupnoteUUID);
await app.replaceNoteContent({ uuid: groupnoteUUID }, groupMarkdown);
await app.navigate(`https://www.amplenote.com/notes/${groupnoteUUID}`);
 
},
/* ----------------------------------- */
"Clickable Links for Tags": async function (app) {
/* ----------------------------------- */
 
// console.log('Tag (Clickable Links) Started');
let notes = [];
notes = await app.filterNotes({ });
// console.log("notes:",notes);
 
// Step 1: Get unique tags and sort them
const noteTags = Array.from(new Set(notes.flatMap(note => note.tags))).sort();
 
// Step 2: Create a function to format the tag into a Markdown link
const formatTagToMarkdownLink = (tag) => {
const formattedUrl = `https://www.amplenote.com/notes?tag=${encodeURIComponent(tag.trim())}`; // Keep the leading dash in URL
const indentLevel = tag.split('/').length - 1; // Count slashes for indent level
const indent = ' '.repeat(indentLevel); // Create indentation
return `${indent}- [${tag}](${formattedUrl})`; // Keep the leading dash in the link text
};
 
// Step 3: Create a set to keep track of existing parent tags
const parentTags = new Set();
 
// Step 4: Build the output
const uniqueMarkdownLinks = new Set(); // Use a Set to avoid duplicates
 
noteTags.forEach(tag => {
// Split the tag to determine the parent hierarchy
const parts = tag.split('/');
let parentPath = '';
 
// Create Markdown link for the tag
const markdownLink = formatTagToMarkdownLink(tag);
 
// Add the tag link to the unique set
uniqueMarkdownLinks.add(markdownLink);
 
// Build the parent path and check for missing parents
parts.forEach(part => {
parentPath += `${part}/`; // Construct parent path
const trimmedPath = parentPath.slice(0, -1); // Remove trailing slash
// If parent path doesn't exist, add it to the set
if (!noteTags.includes(trimmedPath)) {
parentTags.add(trimmedPath);
}
});
});
 
// Add parent tags to uniqueMarkdownLinks if they were not initially in noteTags
parentTags.forEach(parentTag => {
uniqueMarkdownLinks.add(formatTagToMarkdownLink(parentTag));
});
 
// Convert the Set to an array and join for output
const finalMarkdownLinks = Array.from(uniqueMarkdownLinks).join('\n');
 
// Print the result
// console.log(finalMarkdownLinks);
 
const tagMarkdown = `
---
${finalMarkdownLinks}
---
### Details<!-- {"collapsed":true} -->
**Caveat:**
- This brings only Tags which are linked to at least one amplenote. (Fetches all the Tags).
- If a Parent Tag does not contain any notes, then I have added a fix, still it does not do its best.
- Hence having at least one note attached to all the Tags and in all levels, make sense in this case. Rest assured, should be working well.
**For more details:** [Search queries: tag, filter, and other queries](https://www.amplenote.com/help/search_filter_tags_groups)
`;
// console.log("tagMarkdown:",tagMarkdown);
 
// Tag Report
const tagNoteName = `Tag Clickable Links`;
const tagTagName = ['-reports/-tagger-pro'];
const tagnoteUUID = await (async () => {
const existingUUID = await app.settings["Tag_Clickable_Links_UUID [Do not Edit!]"];
if (existingUUID)
return existingUUID;
// console.log("existingUUID:",existingUUID);
const newUUID = await app.createNote(tagNoteName, tagTagName);
await app.setSetting("Tag_Clickable_Links_UUID [Do not Edit!]", newUUID);
return newUUID;
// console.log("newUUID:",newUUID);
})();
// console.log("tagnoteUUID:",tagnoteUUID);
await app.replaceNoteContent({ uuid: tagnoteUUID }, tagMarkdown);
await app.navigate(`https://www.amplenote.com/notes/${tagnoteUUID}`);
 
// console.log('Finished');
},
/* ----------------------------------- */
}
}

linkAdditional Information:


linkChange Log:

July 11th, 2024 - Build the framework and all the basic requirements for this Plugin.

Collected all the necessary codes, templates, and references.

Build the Plugin to handle single tag and multiple tags correctly. Also how to handle new tag and already existing tag.

Fixed all the error handling methods.

Added the feature to prefix and suffix the desired Emoji or Any Text can be added by default.

Added the Predefined Template / Format to handle multiple addition in a single click, after be configured in the Code based on users preferences.

October 17th, 2024

Implemented, tested Correlation Matrix for Tags (Was little tricky, as the Correlation Matrix is very known for using multi valuable and giving a statically valid output to understand the change between two variable, here I had to take up the counts for the same two variable and was able to finalize it. Then finding the right pattern to get the count for notes with single tag, was an additional hurdle, handled it).

Implemented, tested Clickable Links for Groups (Was simple and straight forward to complete, used reference note markdown).

Implemented, tested Clickable Links for Tags (Getting and de-duplicating the tags was fine, but handling different scenarios was the hard part, and getting the indent was also a good learning here. Then the only caveat is all the tags should have a note for this to pick it up and utilize here, especially parent tags, if not note is present, the code creates a dummy link - still not perfect as it drops it at the last).

October 18th, 2024

Added an additional download type as Document Report (Suggested - Simple), and made some changes to the already existing names of the download options for better understanding and decision making process. Tested and rolled out.

November 1st, 2024

Added Include and Exclude Tag Option for the Correlation Count Matrix for Tags.Having both Include and Exclude did not seem to be a required option, hence ignoring it for now.


linkImplemented & Upcoming:

Understanding the Requirements

Build the framework

Lots of emojis + Groupings

Add prefix and suffixing options

Error handling

handle multi tagging array

handle single tagging along with multi tagging array

handling errors and cleanup nulls or empty spaces

adding console logs and testing the requirements

fix multi tags as single tag issue - for loop

handling default options for select position

cleaned up logs for query optimization

minor tweaks

Testing

changes to error logs

handling spaces

Documentation

Final

change log update

time invested update

Gifts - how tos

documentation fixing

publishing

Future Ideas in the Bucket:

Add Tagger to Multiple Notes / A Particular Tag (Exclusion Criteria's - Involved!) - a little risky as multiple notes are involved. - ON HOLD.


Code Explanation! For Curious Readers and Explores! Thank you if you have made till here. You are Awesome, if you are reading this! 😀. Have a Great Day Ahead!


Time Invested For this Plugin: 4h 32m + 7h 20m + 4h 44m + 40m = 17h 18m [Not including the ideas popping up randomly when doing daily rituals, only Screen Time.]