mirror of
https://github.com/taskgenius/taskgenius-plugin.git
synced 2026-07-22 06:40:25 +00:00
feat(fluent): implement dual-mode projects view
Add support for two distinct projects view modes: - Projects overview: displays all projects with ProjectsComponent, disables ProjectList to prevent conflicting navigation - Single project: shows filtered tasks for selected project using ContentComponent, keeps ProjectList enabled When navigating to projects view from Other Views menu, project selection and filters are cleared to enable overview mode. ProjectList interaction is controlled via CSS class and visual feedback. Changes: - FluentSidebar: remove projects exclusion, add setProjectListEnabled() - ProjectList: add setEnabled() method for controlling interaction state - FluentTaskView: clear selection on projects navigation, control list state - FluentComponentManager: switch components based on project selection - fluent-main.css: add disabled project list styles
This commit is contained in:
parent
8fdfc39912
commit
9aaabe716f
5 changed files with 110 additions and 6 deletions
|
|
@ -337,8 +337,8 @@ export class FluentSidebar extends Component {
|
|||
if (!Array.isArray(cfg)) return this.otherItems;
|
||||
|
||||
const primaryIds = new Set(this.primaryItems.map((i) => i.id));
|
||||
// Exclude views that are represented elsewhere in the sidebar (e.g., Projects list)
|
||||
const excludeIds = new Set<string>(["projects"]);
|
||||
// No longer exclude projects view - users can access it from both Projects list and Other Views
|
||||
const excludeIds = new Set<string>([]);
|
||||
const seen = new Set<string>();
|
||||
const items: FluentTaskNavigationItem[] = [];
|
||||
|
||||
|
|
@ -847,4 +847,13 @@ export class FluentSidebar extends Component {
|
|||
this.workspaceSelector?.setWorkspace(workspaceId);
|
||||
this.projectList?.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable project list interaction
|
||||
* Used when showing full projects overview to prevent conflicting navigation
|
||||
*/
|
||||
public setProjectListEnabled(enabled: boolean) {
|
||||
if (!this.projectList) return;
|
||||
this.projectList.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -701,6 +701,18 @@ export class ProjectList extends Component {
|
|||
this.loadProjects();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable project list interaction
|
||||
* Used when showing full projects overview to prevent conflicting navigation
|
||||
*/
|
||||
public setEnabled(enabled: boolean) {
|
||||
if (enabled) {
|
||||
this.containerEl.removeClass("tg-project-list-disabled");
|
||||
} else {
|
||||
this.containerEl.addClass("tg-project-list-disabled");
|
||||
}
|
||||
}
|
||||
|
||||
private handleAddProject(buttonEl: HTMLElement) {
|
||||
// Clean up any existing popover
|
||||
if (this.currentPopover) {
|
||||
|
|
|
|||
|
|
@ -538,9 +538,22 @@ export class FluentComponentManager extends Component {
|
|||
targetComponent = this.tagsComponent;
|
||||
break;
|
||||
case "projects":
|
||||
// In V2, Projects is treated as a content-based view using global project filters
|
||||
targetComponent = this.contentComponent;
|
||||
modeForComponent = viewId;
|
||||
// Two modes for projects view:
|
||||
// 1. With project selection (from ProjectList) → use ContentComponent for filtered tasks
|
||||
// 2. Without project selection (from view navigation) → use ProjectsComponent for overview
|
||||
if (project) {
|
||||
console.log(
|
||||
"[FluentComponent] Projects view with selected project - using ContentComponent",
|
||||
);
|
||||
targetComponent = this.contentComponent;
|
||||
modeForComponent = viewId;
|
||||
} else {
|
||||
console.log(
|
||||
"[FluentComponent] Projects view without selection - using ProjectsComponent",
|
||||
);
|
||||
targetComponent = this.projectsComponent;
|
||||
modeForComponent = viewId;
|
||||
}
|
||||
break;
|
||||
case "review":
|
||||
targetComponent = this.reviewComponent;
|
||||
|
|
@ -591,7 +604,8 @@ export class FluentComponentManager extends Component {
|
|||
// Set tasks on the component
|
||||
if (typeof targetComponent.setTasks === "function") {
|
||||
// Special handling for components that need only all tasks (single parameter)
|
||||
if (viewId === "review" || viewId === "tags") {
|
||||
// Projects overview mode (no project selected) needs all tasks to build project list
|
||||
if (viewId === "review" || viewId === "tags" || (viewId === "projects" && !project)) {
|
||||
console.log(
|
||||
`[FluentComponent] Calling setTasks for ${viewId} with ALL tasks:`,
|
||||
tasks.length,
|
||||
|
|
|
|||
|
|
@ -473,6 +473,44 @@ export class FluentTaskView extends ItemView {
|
|||
this.viewState.viewMode,
|
||||
);
|
||||
this.currentViewId = viewId;
|
||||
|
||||
// When navigating to projects view directly, clear project selection
|
||||
// This enables the full project overview mode
|
||||
if (viewId === "projects") {
|
||||
console.log("[TG] Navigating to projects overview - clearing project selection");
|
||||
this.viewState.selectedProject = undefined;
|
||||
|
||||
// Clear project filter from filter state
|
||||
try {
|
||||
if (this.liveFilterState) {
|
||||
const nextState = { ...this.liveFilterState };
|
||||
nextState.filterGroups = (nextState.filterGroups || [])
|
||||
.map((g: any) => ({
|
||||
...g,
|
||||
filters: (g.filters || []).filter(
|
||||
(f: any) => f.property !== "project",
|
||||
),
|
||||
}))
|
||||
.filter((g: any) => g.filters && g.filters.length > 0);
|
||||
|
||||
this.liveFilterState = nextState as any;
|
||||
this.currentFilterState = nextState as any;
|
||||
this.app.saveLocalStorage(
|
||||
"task-genius-view-filter",
|
||||
nextState,
|
||||
);
|
||||
|
||||
// Broadcast filter change
|
||||
this.app.workspace.trigger(
|
||||
"task-genius:filter-changed",
|
||||
nextState,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("[TG] Failed to clear project filter", e);
|
||||
}
|
||||
}
|
||||
|
||||
const nextMode = this.ensureViewModeForView(viewId);
|
||||
this.viewState.viewMode = nextMode;
|
||||
this.recordViewModeForView(viewId, nextMode);
|
||||
|
|
@ -1031,6 +1069,14 @@ export class FluentTaskView extends ItemView {
|
|||
// Update sidebar active item
|
||||
this.layoutManager.setSidebarActiveItem(this.currentViewId);
|
||||
|
||||
// Control project list interaction based on view state
|
||||
// Disable project list when showing full projects overview (no project selected)
|
||||
// Enable it when in other views or when a specific project is selected
|
||||
const isProjectsOverview =
|
||||
this.currentViewId === "projects" &&
|
||||
!this.viewState.selectedProject;
|
||||
this.layoutManager.sidebar?.setProjectListEnabled(!isProjectsOverview);
|
||||
|
||||
// Show loading state
|
||||
if (this.isLoading) {
|
||||
this.componentManager.renderLoadingState();
|
||||
|
|
|
|||
|
|
@ -380,6 +380,29 @@ button.fluent-new-task-btn:hover {
|
|||
background-color: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
/* Disabled project list styles - used when showing full projects overview */
|
||||
.tg-project-list-disabled {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tg-project-list-disabled::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--background-modifier-cover);
|
||||
opacity: 0.3;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tg-project-list-disabled .fluent-project-item {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Main Container */
|
||||
.tg-fluent-main-container {
|
||||
flex: 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue