fix(app-tauri,frontend): la fenêtre Tâches planifiées s'affiche en mode détaché — #359 (QA verte)
cause: le panneau Tâches planifiées n'avait aucune variante dans l'enum ViewPanel, open_view_window("scheduledTasks") rejetait INVALID et detachPanel ne touchait le placement qu'en cas de succès — même famille que #299, aucun effet visible ni message.
fix: variante ViewPanel::ScheduledTasks avec contrat stable label view-scheduledTasks / url index.html?panel=scheduledTasks / titre « Scheduled tasks », identité persistée des fenêtres view-scheduledTasks acceptée à la restauration #50; frontend ViewWindow rend le ScheduledTasksPanel du projet focalisé et ProjectsView expose le placement Fenêtre détachée via WindowGateway; retrait de la variante Projects devenue morte après #315 — le panneau Projects (coquille de la fenêtre principale) n'est plus détachable, refus INVALID gardé par tests.
QA verte: view_window_tests dont scheduled_tasks_view_window_contract_is_stable et projects_panel_is_not_detachable, persisted_identity_accepts_scheduled_tasks_view_labels, frontend ViewWindow/window gateway/ProjectsView.detach verts.
This commit is contained in:
@ -4440,9 +4440,9 @@ pub struct FocusedProjectChangedEventDto {
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum ViewPanel {
|
||||
Projects,
|
||||
Context,
|
||||
Work,
|
||||
ScheduledTasks,
|
||||
Tickets,
|
||||
Mcp,
|
||||
Agents,
|
||||
@ -4456,9 +4456,9 @@ pub(crate) enum ViewPanel {
|
||||
impl ViewPanel {
|
||||
pub(crate) fn parse(raw: &str) -> Result<Self, ErrorDto> {
|
||||
match raw {
|
||||
"projects" => Ok(Self::Projects),
|
||||
"context" => Ok(Self::Context),
|
||||
"work" => Ok(Self::Work),
|
||||
"scheduledTasks" => Ok(Self::ScheduledTasks),
|
||||
"tickets" => Ok(Self::Tickets),
|
||||
"mcp" => Ok(Self::Mcp),
|
||||
"agents" => Ok(Self::Agents),
|
||||
@ -4476,9 +4476,9 @@ impl ViewPanel {
|
||||
|
||||
pub(crate) const fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Projects => "projects",
|
||||
Self::Context => "context",
|
||||
Self::Work => "work",
|
||||
Self::ScheduledTasks => "scheduledTasks",
|
||||
Self::Tickets => "tickets",
|
||||
Self::Mcp => "mcp",
|
||||
Self::Agents => "agents",
|
||||
@ -4492,9 +4492,9 @@ impl ViewPanel {
|
||||
|
||||
pub(crate) const fn title(self) -> &'static str {
|
||||
match self {
|
||||
Self::Projects => "Projects",
|
||||
Self::Context => "Project context",
|
||||
Self::Work => "Work state",
|
||||
Self::ScheduledTasks => "Scheduled tasks",
|
||||
Self::Tickets => "Tickets",
|
||||
Self::Mcp => "MCP",
|
||||
Self::Agents => "Agents",
|
||||
@ -4814,6 +4814,25 @@ mod view_window_tests {
|
||||
assert_eq!(view_panel_from_window_label("view-mcp"), Some(panel));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scheduled_tasks_view_window_contract_is_stable() {
|
||||
let panel = ViewPanel::parse("scheduledTasks").unwrap();
|
||||
|
||||
assert_eq!(panel, ViewPanel::ScheduledTasks);
|
||||
assert_eq!(panel.as_str(), "scheduledTasks");
|
||||
assert_eq!(panel.title(), "Scheduled tasks");
|
||||
assert_eq!(view_window_label(panel), "view-scheduledTasks");
|
||||
assert_eq!(view_window_url(panel), "index.html?panel=scheduledTasks");
|
||||
assert_eq!(
|
||||
view_panel_from_window_label("view-scheduledTasks"),
|
||||
Some(panel)
|
||||
);
|
||||
assert_eq!(
|
||||
view_panel_from_window_label("view-scheduledTasks-0000000000000000000000000000002a"),
|
||||
Some(panel)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn view_window_rejects_unknown_panel() {
|
||||
let err = ViewPanel::parse("terminal").unwrap_err();
|
||||
@ -4822,6 +4841,15 @@ mod view_window_tests {
|
||||
assert!(err.message.contains("invalid view panel: terminal"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn projects_panel_is_not_detachable() {
|
||||
let err = ViewPanel::parse("projects").unwrap_err();
|
||||
|
||||
assert_eq!(err.code, "INVALID");
|
||||
assert!(err.message.contains("invalid view panel: projects"));
|
||||
assert!(view_panel_from_window_label("view-projects").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn view_window_label_parser_accepts_stable_and_legacy_labels() {
|
||||
assert_eq!(
|
||||
|
||||
@ -1132,6 +1132,26 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persisted_identity_accepts_scheduled_tasks_view_labels() {
|
||||
let (kind, panel, project_id, plugin_layout, url) =
|
||||
persisted_window_identity_from_label("view-scheduledTasks").unwrap();
|
||||
|
||||
assert_eq!(kind, PersistedWindowKind::View);
|
||||
assert_eq!(panel.as_deref(), Some("scheduledTasks"));
|
||||
assert!(project_id.is_none());
|
||||
assert!(plugin_layout.is_none());
|
||||
assert_eq!(url.as_deref(), Some("index.html?panel=scheduledTasks"));
|
||||
assert_eq!(
|
||||
persisted_view_identity_from_label(
|
||||
"view-scheduledTasks-0000000000000000000000000000002a"
|
||||
)
|
||||
.unwrap()
|
||||
.as_str(),
|
||||
"scheduledTasks"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persisted_identity_accepts_plugin_layout_view_labels() {
|
||||
let plugin_id = domain::PluginId::new("dev.idea.android-plugin").unwrap();
|
||||
@ -1157,6 +1177,7 @@ mod tests {
|
||||
fn persisted_identity_filters_unknown_or_headless_labels() {
|
||||
assert!(persisted_window_identity_from_label("mcp-server").is_none());
|
||||
assert!(persisted_window_identity_from_label("settings").is_none());
|
||||
assert!(persisted_window_identity_from_label("view-projects").is_none());
|
||||
assert!(persisted_window_identity_from_label(
|
||||
"view-unknown-0000000000000000000000000000002a"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user