Skip to content

Commit

Permalink
Merge pull request #86 from cloud-atlas-ai/ux-overhaul
Browse files Browse the repository at this point in the history
Command UX overhaul
  • Loading branch information
muness authored Feb 28, 2024
2 parents 2a2b5de + 54d37d8 commit 62daf93
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 87 deletions.
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const DEFAULT_SETTINGS: CloudAtlasPluginSettings = {
endpoint: "",
},
provider: "openai",
registeredFlows: [],
};

export const exampleFlowString = `---
Expand Down
65 changes: 65 additions & 0 deletions src/flow_view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { ItemView, WorkspaceLeaf, setIcon } from "obsidian";
import CloudAtlasPlugin from "./main";

export const CA_VIEW_TYPE = "flow-view";

export class FlowView extends ItemView {
plugin: CloudAtlasPlugin;

constructor(leaf: WorkspaceLeaf, plugin: CloudAtlasPlugin) {
super(leaf);
this.plugin = plugin;
}

getViewType() {
return CA_VIEW_TYPE;
}

getIcon(): string {
return "workflow";
}

getDisplayText() {
return "Cloud Atlas flows view";
}

async onOpen() {
const container = this.containerEl.children[1];
container.empty();
container.createEl("h4", { text: "Cloud Atlas flows" });
const vaultFiles = this.app.vault.getMarkdownFiles();

console.debug(`Found ${vaultFiles.length} vault files`);

const cloudAtlasFlows = vaultFiles.filter(
(file) =>
file.path.startsWith("CloudAtlas/") &&
file.path.endsWith(".flow.md")
).map((f) => f.path.split("/")[1].split(".flow.md")[0]).sort();

console.debug(`Found ${cloudAtlasFlows.length} CloudAtlas flows`);

const ul = container.createEl("ul");
// Create commands for each flow
cloudAtlasFlows.forEach((flow) => {
const table = ul.createEl("table");
table.addClass("cloud-atlas-flow-table");
const tr = table.createEl("tr");
const td2 = tr.createEl("td");
const runBtn = td2.createEl("button", { text: "Run" });
setIcon(runBtn, "play");
runBtn.addClass("cloud-atlas-flow-btn-primary");
runBtn.addEventListener("click", async () => {
// console.debug(`Running flow ${flow}`);
await this.plugin.runFlow(null, flow);
});
const flowNameTd = tr.createEl("td");
flowNameTd.addClass("cloud-atlas-flow-td-half");
flowNameTd.createEl("span", { text: flow });
});
}

async onClose() {
// Nothing to clean up.
}
}
88 changes: 52 additions & 36 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Notice,
Plugin,
TFile,
WorkspaceLeaf,
normalizePath,
} from "obsidian";
import {
Expand Down Expand Up @@ -66,6 +67,7 @@ import {
import { Extension } from "@codemirror/state";
import { randomName } from "./namegenerator";
import { azureAiFetch, openAiFetch } from "./byollm";
import { FlowView, CA_VIEW_TYPE } from "./flow_view";

let noticeTimeout: NodeJS.Timeout;

Expand Down Expand Up @@ -319,27 +321,34 @@ export default class CloudAtlasPlugin extends Plugin {
return respJson;
};

runFlow = async (editor: Editor, flow: string) => {
runFlow = async (editor: Editor | null, flow: string) => {
console.log("Running flow: ", flow);
const inputFlowFile = this.app.workspace.getActiveFile();

if (!inputFlowFile) {
console.debug("No active file");
new Notice("No active file in the editor, open one and try again.");
return null;
}

const input = editor.getSelection();
const input = editor?.getSelection();
const fromSelection = Boolean(input);

if (fromSelection) {
editor.replaceSelection(
editor?.replaceSelection(
input +
"\n\n---\n\n" +
`\u{1F4C4}\u{2194}\u{1F916}` +
"\n\n---\n\n"
);
} else {
editor.replaceSelection(
"\n\n---\n\n" + `\u{1F4C4}\u{2194}\u{1F916}` + "\n\n---\n\n"
);
const current = await this.app.vault.read(inputFlowFile);
const output =
current +
"\n\n---\n\n" +
`\u{1F4C4}\u{2194}\u{1F916}` +
"\n\n---\n\n";
await this.app.vault.modify(inputFlowFile, output);
}

const notice = new Notice(`Running ${flow} flow ...`, 0);
Expand Down Expand Up @@ -875,29 +884,47 @@ export default class CloudAtlasPlugin extends Plugin {
);
}

addFlowCommands = async () => {
const vaultFiles = this.app.vault.getMarkdownFiles();

console.debug(`Found ${vaultFiles.length} vault files`);

const cloudAtlasFlows = vaultFiles.filter(
(file) =>
file.path.startsWith("CloudAtlas/") &&
file.path.endsWith(".flow.md")
);
addFlowCommands = () => {
// Create commands for each flow registered in the settings

console.debug(`Found ${cloudAtlasFlows.length} CloudAtlas flows`);
console.debug("Registered flows: ", this.settings.registeredFlows);

// Create commands for each flow
cloudAtlasFlows.forEach((flowFile) => {
const flow = flowFile.path.split("/")[1].split(".flow.md")[0];
this.settings.registeredFlows.forEach((flow) => {
this.addNewCommand(this, flow);
});
};

async activateView() {
const { workspace } = this.app;

let leaf: WorkspaceLeaf | null = null;
const leaves = workspace.getLeavesOfType(CA_VIEW_TYPE);

if (leaves.length > 0) {
// A leaf with our view already exists, use that
leaf = leaves[0];
} else {
// Our view could not be found in the workspace, create a new leaf
// in the right sidebar for it
leaf = workspace.getRightLeaf(false);
await leaf.setViewState({ type: CA_VIEW_TYPE, active: true });
}

// "Reveal" the leaf in case it is in a collapsed sidebar
workspace.revealLeaf(leaf);
}

async onload() {
console.debug("Entering onLoad");

this.addRibbonIcon("workflow", "Cloud Atlas flows", () => {
try {
this.activateView();
} catch (e) {
console.debug(e);
}
});

await this.loadSettings();
console.debug("Loaded settings");

Expand All @@ -920,10 +947,7 @@ export default class CloudAtlasPlugin extends Plugin {
);

await this.createFolder("CloudAtlas");

await this.create("CloudAtlas/example.flow.md", exampleFlowString);

// await this.createFlow("Example");
new Notice(
"Created CloudAtlas folder with an example flow. Please configure the plugin to use it."
);
Expand All @@ -932,9 +956,6 @@ export default class CloudAtlasPlugin extends Plugin {
}
console.debug("Bootstraped CloudAtlas folder");

await sleep(100);
this.addFlowCommands();

this.addCommand({
id: `create-flow`,
name: `Create new flow`,
Expand All @@ -948,18 +969,12 @@ export default class CloudAtlasPlugin extends Plugin {
},
});

this.addCommand({
id: "refresh",
name: "Refresh",
callback: async () => {
this.addFlowCommands();
new Notice("Refreshed Cloud Atlas flows");
},
});
this.addFlowCommands();
this.activateView();

this.addCommand({
id: `run-canvas-flow`,
name: `Run Canvas Flow`,
name: `Run Canvas flow`,
checkCallback: (checking: boolean) => {
const noteFile = this.app.workspace.getActiveFile();
if (noteFile) {
Expand All @@ -973,6 +988,7 @@ export default class CloudAtlasPlugin extends Plugin {
},
});

this.registerView(CA_VIEW_TYPE, (leaf) => new FlowView(leaf, this));
this.addSettingTab(new CloudAtlasGlobalSettingsTab(this.app, this));
}

Expand All @@ -995,7 +1011,7 @@ export default class CloudAtlasPlugin extends Plugin {
console.debug("Adding command for flow: ", flow);
this.addCommand({
id: `run-flow-${flow}`,
name: `Run ${flow} Flow`,
name: `Run ${flow} flow`,
editorCallback: async (editor: Editor, view: MarkdownView) => {
await this.runFlow(editor, flow);
},
Expand Down
72 changes: 36 additions & 36 deletions src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ export interface CloudAtlasPluginSettings {
openAiSettings: OpenAiSettings;
azureAiSettings: AzureAiSettings;
provider: string;
registeredFlows: string[];
}

// TODO: If we only have one tab, we shouldn't have multiple tabs or this will get rejected when we submit it to the store.
export class CloudAtlasGlobalSettingsTab extends PluginSettingTab {
plugin: CloudAtlasPlugin;

Expand Down Expand Up @@ -69,7 +69,7 @@ export class CloudAtlasGlobalSettingsTab extends PluginSettingTab {
dropDown.addOption("openai", "OpenAI");
// dropDown.addOption('azureai', 'AzureAI');
dropDown.addOption("cloudatlas", "Cloud Atlas");
dropDown.setValue(this.plugin.settings.provider);
dropDown.setValue(this.plugin.settings.provider);
dropDown.onChange(async (value) => {
this.plugin.settings.provider = value;
this.display();
Expand Down Expand Up @@ -282,40 +282,6 @@ export class CloudAtlasGlobalSettingsTab extends PluginSettingTab {
await this.plugin.saveSettings();
})
);

new Setting(containerEl)
.setName("Entity recognition")
.setDesc(
"Run named entity recognition on submitted notes, results in more relevant context entries, leading to more useful returns."
)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.entityRecognition)
.onChange(async (value) => {
this.plugin.settings.entityRecognition = value;
await this.plugin.saveSettings();
})
);

new Setting(containerEl)
.setName("Generate embeddings")
.setDesc(
"Generate embeddings for submitted notes, allows us to use retrieveal augmented generation."
)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.generateEmbeddings)
.onChange(async (value) => {
this.plugin.settings.generateEmbeddings = value;
await this.plugin.saveSettings();
})
);

containerEl.createEl("h2", { text: "Wikify" });

this.wikifySetting(containerEl, NamedEntity.Person);
this.wikifySetting(containerEl, NamedEntity.Location);

containerEl.createEl("h2", { text: "Canvas Flows" });

new Setting(containerEl)
Expand Down Expand Up @@ -361,6 +327,40 @@ export class CloudAtlasGlobalSettingsTab extends PluginSettingTab {
await this.plugin.saveSettings();
})
);
containerEl.createEl("h2", { text: "Register commands" });
const vaultFiles = this.app.vault.getMarkdownFiles();
const cloudAtlasFlows = vaultFiles.filter(
(file) =>
file.path.startsWith("CloudAtlas/") &&
file.path.endsWith(".flow.md")
);
cloudAtlasFlows.forEach((flow) => {
const name = flow.path.split("/")[1].split(".flow.md")[0];
new Setting(containerEl)
.setName(name)
.setDesc(`Register ${name} command`)
.addToggle((toggle) => {
toggle
.setValue(
this.plugin.settings.registeredFlows.indexOf(
name
) > -1
)
.onChange(async (value) => {
if (value) {
this.plugin.settings.registeredFlows.push(
name
);
} else {
this.plugin.settings.registeredFlows =
this.plugin.settings.registeredFlows.filter(
(flow) => flow !== name
);
}
await this.plugin.saveSettings();
});
});
});
}
}
}
Expand Down
Loading

0 comments on commit 62daf93

Please sign in to comment.