forketyfork_obsidian-youtra.../YouTrackIssueModal.ts

124 lines
3.3 KiB
TypeScript

import { App, Modal, TextComponent, normalizePath } from "obsidian";
import type YouTrackPlugin from "./YouTrackPlugin";
export default class YouTrackIssueModal extends Modal {
plugin: YouTrackPlugin;
issueId: string;
statusEl: HTMLElement;
loadingIndicator: HTMLElement;
constructor(app: App, plugin: YouTrackPlugin) {
super(app);
this.plugin = plugin;
}
onOpen() {
const { contentEl } = this;
contentEl.createEl("h2", { text: "Fetch YouTrack issue" });
// Create input field for issue ID
const inputContainer = contentEl.createDiv({ cls: "youtrack-input-container" });
const input = new TextComponent(inputContainer)
.setPlaceholder("Issue URL or ID (e.g., ABC-123)")
.setValue(this.issueId || "")
.onChange(value => {
this.issueId = value;
// Clear any previous error messages
if (this.statusEl) {
this.statusEl.setText("");
}
});
input.inputEl.addClass("youtrack-input");
// Create status element for messages
this.statusEl = contentEl.createEl("p", { cls: "youtrack-status" });
// Create loading indicator (hidden by default)
this.loadingIndicator = contentEl.createEl("div", {
cls: "youtrack-loading",
text: "Fetching issue...",
});
// Focus the input field and select all text
setTimeout(() => {
input.inputEl.focus();
input.inputEl.select();
}, 0);
// Create buttons container
const buttonsContainer = contentEl.createDiv({
cls: "youtrack-modal-button-container",
});
// Add cancel button
buttonsContainer.createEl("button", { text: "Cancel" }).addEventListener("click", () => {
this.close();
});
// Add fetch button
const fetchButton = buttonsContainer.createEl("button", {
text: "Fetch issue",
cls: "mod-cta",
});
const fetchIssue = async () => {
if (!this.issueId) {
this.statusEl.setText("Please enter an issue ID or URL");
this.statusEl.addClass("error-message");
return;
}
const parsedId = this.plugin.parseIssueId(this.issueId);
if (!parsedId) {
this.statusEl.setText("Invalid issue ID or URL (must match your YouTrack URL)");
this.statusEl.addClass("error-message");
return;
}
if (this.plugin.settings.templatePath) {
const normalizedPath = normalizePath(this.plugin.settings.templatePath);
const exists = await this.plugin.app.vault.adapter.exists(normalizedPath);
if (!exists) {
this.statusEl.setText(
`Template file not found: ${normalizedPath}. Please check the template path in settings.`
);
this.statusEl.addClass("error-message");
return;
}
}
// Show loading indicator
this.loadingIndicator.classList.add("visible");
this.statusEl.setText("");
try {
await this.plugin.importIssue(parsedId);
this.close();
} catch (error) {
// Hide loading indicator
this.loadingIndicator.classList.remove("visible");
// Show error message
const errorMessage = error instanceof Error ? error.message : String(error);
this.statusEl.setText(`Error: ${errorMessage}`);
this.statusEl.addClass("error-message");
}
};
fetchButton.addEventListener("click", () => {
fetchIssue().catch(console.error);
});
// Handle Enter key press
input.inputEl.addEventListener("keypress", event => {
if (event.key === "Enter") {
fetchIssue().catch(console.error);
}
});
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
}