mirror of
https://github.com/taskgenius/taskgenius-plugin.git
synced 2026-07-22 06:40:25 +00:00
feat(settings): add workspace selector component
Add a new workspace selector component to the settings tab that allows users to switch between different workspace configurations. The selector displays the current workspace icon and name, and provides a dropdown menu to switch between available workspaces. - Create WorkspaceSettingsSelector component with workspace switching - Add styling for the workspace selector UI - Support workspace icon display and hover effects - Integrate with existing workspace manager
This commit is contained in:
parent
41f1d95576
commit
27c426c474
2 changed files with 278 additions and 0 deletions
|
|
@ -0,0 +1,148 @@
|
|||
import { Menu, setIcon } from "obsidian";
|
||||
import type TaskProgressBarPlugin from "@/index";
|
||||
import { WorkspaceData } from "@/experimental/v2/types/workspace";
|
||||
import { t } from "@/translations/helper";
|
||||
import { TaskProgressBarSettingTab } from "@/setting";
|
||||
|
||||
export class WorkspaceSettingsSelector {
|
||||
private containerEl: HTMLElement;
|
||||
private plugin: TaskProgressBarPlugin;
|
||||
private settingTab: TaskProgressBarSettingTab;
|
||||
private currentWorkspaceId: string;
|
||||
private buttonEl: HTMLElement;
|
||||
|
||||
constructor(
|
||||
containerEl: HTMLElement,
|
||||
plugin: TaskProgressBarPlugin,
|
||||
settingTab: TaskProgressBarSettingTab
|
||||
) {
|
||||
this.containerEl = containerEl;
|
||||
this.plugin = plugin;
|
||||
this.settingTab = settingTab;
|
||||
this.currentWorkspaceId =
|
||||
plugin.workspaceManager?.getActiveWorkspace().id || "";
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
private render() {
|
||||
// Create workspace selector container
|
||||
const selectorContainer = this.containerEl.createDiv({
|
||||
cls: "workspace-settings-selector",
|
||||
});
|
||||
|
||||
if (!this.plugin.workspaceManager) return;
|
||||
|
||||
const currentWorkspace =
|
||||
this.plugin.workspaceManager.getActiveWorkspace();
|
||||
|
||||
this.buttonEl = selectorContainer.createDiv({
|
||||
cls: "workspace-settings-selector-button",
|
||||
});
|
||||
|
||||
// Workspace icon
|
||||
const workspaceIcon = this.buttonEl.createDiv({
|
||||
cls: "workspace-icon",
|
||||
});
|
||||
setIcon(workspaceIcon, currentWorkspace.icon || "layers");
|
||||
|
||||
// Workspace name
|
||||
const workspaceName = this.buttonEl.createSpan({
|
||||
cls: "workspace-name",
|
||||
text: currentWorkspace.name,
|
||||
});
|
||||
|
||||
// Dropdown arrow
|
||||
const dropdownIcon = this.buttonEl.createDiv({
|
||||
cls: "workspace-dropdown-icon",
|
||||
});
|
||||
setIcon(dropdownIcon, "chevron-down");
|
||||
|
||||
// Click handler
|
||||
this.buttonEl.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.showWorkspaceMenu(e);
|
||||
});
|
||||
}
|
||||
|
||||
private showWorkspaceMenu(event: MouseEvent) {
|
||||
if (!this.plugin.workspaceManager) return;
|
||||
|
||||
const menu = new Menu();
|
||||
const workspaces = this.plugin.workspaceManager.getAllWorkspaces();
|
||||
const currentWorkspace =
|
||||
this.plugin.workspaceManager.getActiveWorkspace();
|
||||
|
||||
// Add workspace items for switching
|
||||
workspaces.forEach((workspace) => {
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(workspace.name)
|
||||
.setIcon(workspace.icon || "layers")
|
||||
.onClick(async () => {
|
||||
await this.switchWorkspace(workspace.id);
|
||||
});
|
||||
|
||||
// Mark current workspace with checkmark
|
||||
if (workspace.id === currentWorkspace.id) {
|
||||
item.setChecked(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Add separator
|
||||
menu.addSeparator();
|
||||
|
||||
// Add "Manage Workspaces..." option to navigate to settings
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(t("Manage Workspaces..."))
|
||||
.setIcon("settings")
|
||||
.onClick(() => {
|
||||
// Navigate to workspace settings tab
|
||||
this.settingTab.switchToTab("workspaces");
|
||||
});
|
||||
});
|
||||
|
||||
menu.showAtMouseEvent(event);
|
||||
}
|
||||
|
||||
private async switchWorkspace(workspaceId: string) {
|
||||
if (!this.plugin.workspaceManager) return;
|
||||
|
||||
// Switch workspace
|
||||
await this.plugin.workspaceManager.setActiveWorkspace(workspaceId);
|
||||
this.currentWorkspaceId = workspaceId;
|
||||
|
||||
// Update button display
|
||||
this.updateDisplay();
|
||||
|
||||
// Trigger settings reload to reflect workspace change
|
||||
await this.plugin.saveSettings();
|
||||
this.settingTab.applySettingsUpdate();
|
||||
}
|
||||
|
||||
private updateDisplay() {
|
||||
if (!this.plugin.workspaceManager || !this.buttonEl) return;
|
||||
|
||||
const currentWorkspace =
|
||||
this.plugin.workspaceManager.getActiveWorkspace();
|
||||
|
||||
// Update icon
|
||||
const iconEl = this.buttonEl.querySelector(".workspace-icon");
|
||||
if (iconEl) {
|
||||
iconEl.empty();
|
||||
setIcon(iconEl as HTMLElement, currentWorkspace.icon || "layers");
|
||||
}
|
||||
|
||||
// Update name
|
||||
const nameEl = this.buttonEl.querySelector(".workspace-name");
|
||||
if (nameEl) {
|
||||
nameEl.textContent = currentWorkspace.name;
|
||||
}
|
||||
}
|
||||
|
||||
public setWorkspace(workspaceId: string) {
|
||||
this.currentWorkspaceId = workspaceId;
|
||||
this.updateDisplay();
|
||||
}
|
||||
}
|
||||
130
src/styles/workspace-settings-selector.css
Normal file
130
src/styles/workspace-settings-selector.css
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/* Workspace Settings Selector Styles */
|
||||
|
||||
/* Main container for the header bar */
|
||||
.tg-settings-header-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Container for workspace selector */
|
||||
.tg-workspace-selector-container {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Workspace selector button */
|
||||
.workspace-settings-selector {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.workspace-settings-selector-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 12px;
|
||||
background-color: var(--background-modifier-form-field);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
min-width: 150px;
|
||||
height: 34px; /* Match search bar height */
|
||||
}
|
||||
|
||||
.workspace-settings-selector-button:hover {
|
||||
background-color: var(--background-modifier-hover);
|
||||
border-color: var(--background-modifier-border-hover);
|
||||
}
|
||||
|
||||
.workspace-settings-selector-button:active {
|
||||
background-color: var(--background-modifier-active-hover);
|
||||
}
|
||||
|
||||
/* Workspace icon */
|
||||
.workspace-settings-selector-button .workspace-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.workspace-settings-selector-button .workspace-icon svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Workspace name */
|
||||
.workspace-settings-selector-button .workspace-name {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
color: var(--text-normal);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Dropdown arrow icon */
|
||||
.workspace-settings-selector-button .workspace-dropdown-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.workspace-settings-selector-button .workspace-dropdown-icon svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
fill: var(--text-muted);
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
.workspace-settings-selector-button:hover .workspace-dropdown-icon svg {
|
||||
fill: var(--text-normal);
|
||||
}
|
||||
|
||||
/* Adjust search container to take remaining space */
|
||||
.tg-settings-header-bar .tg-settings-search-container {
|
||||
flex: 1;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
/* Ensure search input container fills width */
|
||||
.tg-settings-header-bar .tg-settings-search-input-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Main container adjustments */
|
||||
.tg-settings-main-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Ensure search results appear below the header bar */
|
||||
.tg-settings-main-container .tg-settings-search-results {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* Mobile responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.tg-settings-header-bar {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.workspace-settings-selector-button {
|
||||
width: 100%;
|
||||
min-width: unset;
|
||||
}
|
||||
|
||||
.tg-settings-header-bar .tg-settings-search-container {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue