format view and add frontend scoring

This commit is contained in:
Joseph Cochran 2023-06-06 13:34:09 -05:00
parent dd212a0d57
commit bb2b176338
3 changed files with 114 additions and 50 deletions

66
main.ts
View File

@ -1,7 +1,9 @@
import { App, Editor, MarkdownView, Modal, EventRef, Plugin, PluginSettingTab, Setting, View, Workspace, WorkspaceLeaf, getAllTags, MetadataCache, CachedMetadata } from 'obsidian'; import { Console } from 'console';
import { App, Editor, MarkdownView, Modal, FrontMatterCache, Plugin, PluginSettingTab, Setting, View, Workspace, WorkspaceLeaf, getAllTags, MetadataCache, CachedMetadata, TagCache, TAbstractFile, TFile } from 'obsidian';
import { PromptModal } from 'src/Modals/PromptModal'; import { PromptModal } from 'src/Modals/PromptModal';
import { Notes } from 'src/Models/Notes'; import { Notes } from 'src/Models/Notes';
import { VIEW_TYPE_EXAMPLE, PromptView } from 'src/PromptView'; import { LEARNING_TYPE, PromptView } from 'src/PromptView';
import { json } from 'stream/consumers';
// Remember to rename these classes and interfaces! // Remember to rename these classes and interfaces!
@ -17,28 +19,10 @@ export default class Learning extends Plugin {
settings: MyPluginSettings; settings: MyPluginSettings;
private notes: Array<Notes> private notes: Array<Notes>
async activateView() {
this.app.workspace.detachLeavesOfType(VIEW_TYPE_EXAMPLE);
await this.app.workspace.getLeaf(false).setViewState({
type: VIEW_TYPE_EXAMPLE,
active: true,
});
this.app.workspace.revealLeaf(
this.app.workspace.getLeavesOfType(VIEW_TYPE_EXAMPLE)[0]
);
}
async onload() { async onload() {
await this.loadSettings(); await this.loadSettings();
this.notes = [] this.notes = []
this.registerView(
VIEW_TYPE_EXAMPLE,
(leaf) => new PromptView(leaf)
)
this.app.workspace.onLayoutReady( () => { this.app.workspace.onLayoutReady( () => {
const files = this.app.vault.getMarkdownFiles() const files = this.app.vault.getMarkdownFiles()
let notes: Notes[] = []; let notes: Notes[] = [];
@ -58,7 +42,6 @@ export default class Learning extends Plugin {
// This creates an icon in the left ribbon. // This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon('star', 'Learning', (evt: MouseEvent) => { const ribbonIconEl = this.addRibbonIcon('star', 'Learning', (evt: MouseEvent) => {
// Called when the user clicks the icon. // Called when the user clicks the icon.
this.app.workspace.detachLeavesOfType(VIEW_TYPE_EXAMPLE);
new PromptModal(this.app, this.notes).open() new PromptModal(this.app, this.notes).open()
}); });
// Perform additional things with the ribbon // Perform additional things with the ribbon
@ -76,6 +59,7 @@ export default class Learning extends Plugin {
new SampleModal(this.app).open(); new SampleModal(this.app).open();
} }
}); });
// This adds an editor command that can perform some operation on the current editor instance // This adds an editor command that can perform some operation on the current editor instance
this.addCommand({ this.addCommand({
id: 'sample-editor-command', id: 'sample-editor-command',
@ -84,6 +68,7 @@ export default class Learning extends Plugin {
editor.replaceSelection('Sample Editor Command'); editor.replaceSelection('Sample Editor Command');
} }
}); });
// This adds a complex command that can check whether the current state of the app allows execution of the command // This adds a complex command that can check whether the current state of the app allows execution of the command
this.addCommand({ this.addCommand({
id: 'open-sample-modal-complex', id: 'open-sample-modal-complex',
@ -95,7 +80,7 @@ export default class Learning extends Plugin {
// If checking is true, we're simply "checking" if the command can be run. // If checking is true, we're simply "checking" if the command can be run.
// If checking is false, then we want to actually perform the operation. // If checking is false, then we want to actually perform the operation.
if (!checking) { if (!checking) {
new SampleModal(this.app).open(); new PromptModal(this.app, this.notes).open()
} }
// This command will only show up in Command Palette when the check function returns true // This command will only show up in Command Palette when the check function returns true
@ -109,14 +94,47 @@ export default class Learning extends Plugin {
// If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin) // If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin)
// Using this function will automatically remove the event listener when this plugin is disabled. // Using this function will automatically remove the event listener when this plugin is disabled.
this.registerDomEvent(document, 'click', (evt: MouseEvent) => { this.registerDomEvent(document, 'click', async (evt: PointerEvent) => {
console.log('click', evt); const element = evt.composedPath()[0] as HTMLInputElement;
if(element.id.contains("learning-plugin")){
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
if (activeView) {
const file = activeView.file;
const metadata = this.app.metadataCache.getFileCache(file);
const newTag = { tag: "hm", position: { start: { line: 0, col: 0, offset: 0 }, end: { line: 0, col: 0, offset: 0 } } };
metadata?.tags?.push(newTag)
let content = await this.app.vault.read(file)
let finalContent = ""
if (content.includes('learning-score')){
const regex = /#learning-score-\d+/g
finalContent = content.replace(regex, `#learning-score-${element.value}`)
} else
{
finalContent = content + `\n\n\n #learning-score-${element.value}`
}
this.app.vault.modify(file, finalContent)
}
}
}); });
this.registerEvent(
this.app.workspace.on('file-open', this.onFileOpen)
)
// When registering intervals, this function will automatically clear the interval when the plugin is disabled. // When registering intervals, this function will automatically clear the interval when the plugin is disabled.
this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000));
} }
onFileOpen = async (file: TFile) => {
// Do something on file open
}
onunload() { onunload() {
} }

View File

@ -1,13 +1,11 @@
import { Modal, App, DropdownComponent } from 'obsidian' import { Modal, App, TAbstractFile, TFile } from 'obsidian'
import { Notes } from 'src/Models/Notes' import { Notes } from 'src/Models/Notes'
const myTokenizer = (text: string) => { import { PromptView, LEARNING_TYPE } from 'src/PromptView';
const tokens = text.split(/\s+/);
return tokens.filter((token) => token.includes('_') || token.includes('-') || token.length > 1);
};
export class PromptModal extends Modal { export class PromptModal extends Modal {
private notes: Array<Notes> private notes: Array<Notes>
private docs: Array<any> private docs: Array<any>
private file: TAbstractFile | null
constructor(app: App, notes: Notes[]) { constructor(app: App, notes: Notes[]) {
super(app); super(app);
@ -31,7 +29,8 @@ export class PromptModal extends Modal {
const value = (doc as { value: String }).value const value = (doc as { value: String }).value
const lowerCase = value.toLowerCase() const lowerCase = value.toLowerCase()
const formattedValue = lowerCase.substring(1) const formattedValue = lowerCase.substring(1)
if (formattedValue.contains(input) || value.contains(input)) {
if ((formattedValue.contains(input) || value.contains(input)) && !value.contains("learning-score")) {
if(!suggestions.contains(value.toString())) { if(!suggestions.contains(value.toString())) {
suggestions.push({tag: value.toString(), titles: doc.titles, paths: doc.paths }) suggestions.push({tag: value.toString(), titles: doc.titles, paths: doc.paths })
} }
@ -76,13 +75,12 @@ export class PromptModal extends Modal {
suggestionsContainer.style.visibility = 'hidden' suggestionsContainer.style.visibility = 'hidden'
} }
suggestions.forEach((sugg) => { suggestions.forEach((suggestion) => {
const item = document.createElement('div') const item = document.createElement('div')
item.textContent = sugg.tag item.textContent = suggestion.tag
item.addEventListener('mouseenter', () => { item.addEventListener('mouseenter', () => {
item.style.color = 'grey' item.style.color = 'grey'
console.log("hover: " + item.textContent)
}) })
item.addEventListener('mouseleave', () => { item.addEventListener('mouseleave', () => {
@ -90,16 +88,13 @@ export class PromptModal extends Modal {
}) })
item.addEventListener('click', async () => { item.addEventListener('click', async () => {
const VIEW_TYPE_EXAMPLE = "LearningView";
await this.app.workspace.getLeaf(false).setViewState({ await this.app.workspace.getLeaf(false).setViewState({
type: VIEW_TYPE_EXAMPLE, type: LEARNING_TYPE,
active: true, active: true,
}); });
this.app.workspace.revealLeaf( const leaf = this.app.workspace.getLeavesOfType(LEARNING_TYPE)[0]
this.app.workspace.getLeavesOfType(VIEW_TYPE_EXAMPLE)[0] this.app.workspace.getLeaf().open(new PromptView(leaf, suggestion))
);
this.app.workspace.onLayoutReady( () => { this.app.workspace.onLayoutReady( () => {
this.close(); this.close();

View File

@ -1,27 +1,78 @@
import { ItemView, WorkspaceLeaf } from "obsidian"; import { ItemView, TAbstractFile, TFile, WorkspaceLeaf } from "obsidian";
export const VIEW_TYPE_EXAMPLE = "LearningView"; export const LEARNING_TYPE = "LearningView";
export class PromptView extends ItemView { export class PromptView extends ItemView {
constructor(leaf: WorkspaceLeaf) { private params: any
private file: TAbstractFile | null
constructor(leaf: WorkspaceLeaf, params: any) {
super(leaf); super(leaf);
this.params = params
} }
getViewType() { getViewType() {
return VIEW_TYPE_EXAMPLE; return LEARNING_TYPE;
} }
getDisplayText() { getDisplayText() {
return "Example view"; return "Example view";
} }
async onload() {
}
async onOpen() { async onOpen() {
const container = this.containerEl.children[1]; const filteredTitles = this.params.titles.filter((str: string) => !str.includes("[Learning-Plugin]"));
container.empty();
container.createEl("h4", { text: "Example view" }); let fileName = filteredTitles[0];
const lastPeriodIndex = fileName.lastIndexOf(".");
if (lastPeriodIndex !== -1) {
const beforePeriod = fileName.slice(0, lastPeriodIndex);
fileName = `[Learning-Plugin]-${beforePeriod}${fileName.slice(lastPeriodIndex)}`;
}
const originalFile = this.app.vault.getAbstractFileByPath(filteredTitles[0])
let content = await this.app.vault.read(originalFile as TFile)
const formattedContent = content.replace(/[\r\n]+/g, '\n>')
content = '>[!INFO]- ' + formattedContent
content += '\n\n\n\n<form id="learning_level">\
<input type="radio" id="learning-plugin-option0" name="radioOptions" value="0" onchange="()=>{console.log("clicked")}">\
<label for="option0">0</label>\
<br>\
<input type="radio" id="learning-plugin-option0" name="radioOptions" value="1" onchange="handleRadioChange(this)">\
<label for="option1">1</label>\
<br>\
<input type="radio" id="learning-plugin-option0" name="radioOptions" value="2" onchange="handleRadioChange(this)">\
<label for="option2">2</label>\
<br>\
<input type="radio" id="learning-plugin-option0" name="radioOptions" value="3" onchange="handleRadioChange(this)">\
<label for="option3">3</label>\
<br>\
<input type="radio" id="learning-plugin-option0" name="radioOptions" value="4" onchange="handleRadioChange(this)">\
<label for="option4">4</label>\
</form>'
try {
this.file = await this.app.vault.create(fileName, content)
await this.app.workspace.openLinkText(fileName, fileName, true, { state: { mode: 'preview' } })
}
catch(error) {
await this.app.workspace.openLinkText(fileName, fileName, false, { state: { mode: 'preview' } })
}
} }
async onClose() { async onClose() {
// Nothing to clean up. console.log("closed")
this.app.workspace.detachLeavesOfType(LEARNING_TYPE);
} }
} }