fix(git): fix 17 missing async/await bugs + UX overhaul

Backend:
- fix 17 missing 'await' in git route handlers causing silent no-ops
  (branches, diff, history, commit, push, pull, merge, promote, sync)
- fix async coroutine passed to run_blocking in git_plugin.py

Frontend:
- add collapsible 'How it works' onboarding (GitHelpPanel)
- add status legend with color-coded repository statuses
- i18n: add 50+ missing keys, replace hardcoded strings
- add Refresh button in modal header
- add PROD deploy confirmation dialog (replaces browser prompt())
- add CommitHistory to workspace tab with timeline nodes
- add post-commit success banner with next-step guidance
- increase success toast duration to 8s
- group local/remote branches in selector (optgroup)
- format last_modified dates timezone-aware
- change PROD badge from red to neutral indigo
- extract shared resolveGitStatusToken to git-utils.ts
- fix 'slug' label regression
- remove dead init_repo_button key

UI/UX audit fixes:
- add descriptions to Create/Init buttons in init panel
- add actionable CTA to server mismatch warning
- improve checkbox text phrasing
This commit is contained in:
2026-07-01 20:47:25 +03:00
parent 7613ad37ae
commit 64564da988
44 changed files with 1201 additions and 262 deletions

View File

@@ -42,7 +42,7 @@ async def get_merge_status(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
return _gs.get_merge_status(dashboard_id)
return await _gs.get_merge_status(dashboard_id)
except HTTPException:
raise
except Exception as e:
@@ -71,7 +71,7 @@ async def get_merge_conflicts(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
return _gs.get_merge_conflicts(dashboard_id)
return await _gs.get_merge_conflicts(dashboard_id)
except HTTPException:
raise
except Exception as e:
@@ -99,7 +99,7 @@ async def resolve_merge_conflicts(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
resolved_files = _gs.resolve_merge_conflicts(
resolved_files = await _gs.resolve_merge_conflicts(
dashboard_id,
[item.model_dump() for item in resolve_data.resolutions],
)
@@ -129,7 +129,7 @@ async def abort_merge(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
return _gs.abort_merge(dashboard_id)
return await _gs.abort_merge(dashboard_id)
except HTTPException:
raise
except Exception as e:
@@ -157,7 +157,7 @@ async def continue_merge(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
return _gs.continue_merge(dashboard_id, continue_data.message)
return await _gs.continue_merge(dashboard_id, continue_data.message)
except HTTPException:
raise
except Exception as e:

View File

@@ -122,7 +122,7 @@ async def promote_dashboard(
reason,
)
await _apply_git_identity_from_profile(dashboard_id, db, current_user)
result = _gs.promote_direct_merge(
result = await _gs.promote_direct_merge(
dashboard_id=dashboard_id,
from_branch=from_branch,
to_branch=to_branch,

View File

@@ -51,7 +51,7 @@ async def commit_changes(
dashboard_ref, config_manager, env_id
)
await _apply_git_identity_from_profile(dashboard_id, db, current_user)
_gs.commit_changes(
await _gs.commit_changes(
dashboard_id, commit_data.message, commit_data.files
)
return {"status": "success"}
@@ -80,7 +80,7 @@ async def push_changes(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
_gs.push_changes(dashboard_id)
await _gs.push_changes(dashboard_id)
return {"status": "success"}
except HTTPException:
raise
@@ -143,7 +143,7 @@ async def pull_changes(
extra={"src": "pull_changes"},
)
await _apply_git_identity_from_profile(dashboard_id, db, current_user)
_gs.pull_changes(dashboard_id)
await _gs.pull_changes(dashboard_id)
return {"status": "success"}
except HTTPException:
raise
@@ -235,7 +235,7 @@ async def get_repository_diff(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
return _gs.get_diff(dashboard_id, file_path, staged)
return await _gs.get_diff(dashboard_id, file_path, staged)
except HTTPException:
raise
except Exception as e:
@@ -262,7 +262,7 @@ async def get_history(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
return _gs.get_commit_history(dashboard_id, limit)
return await _gs.get_commit_history(dashboard_id, limit)
except HTTPException:
raise
except Exception as e:
@@ -290,14 +290,14 @@ async def generate_commit_message(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
diff = _gs.get_diff(dashboard_id, staged=True)
diff = await _gs.get_diff(dashboard_id, staged=True)
if not diff:
diff = _gs.get_diff(dashboard_id, staged=False)
diff = await _gs.get_diff(dashboard_id, staged=False)
if not diff:
return {"message": "No changes detected"}
history_objs = _gs.get_commit_history(dashboard_id, limit=5)
history_objs = await _gs.get_commit_history(dashboard_id, limit=5)
history = [h.message for h in history_objs if hasattr(h, "message")]
from src.plugins.llm_analysis.models import LLMProviderType

View File

@@ -193,7 +193,7 @@ async def get_branches(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
return _gs.list_branches(dashboard_id)
return await _gs.list_branches(dashboard_id)
except HTTPException:
raise
except Exception as e:
@@ -223,7 +223,7 @@ async def create_branch(
dashboard_ref, config_manager, env_id
)
await _apply_git_identity_from_profile(dashboard_id, db, current_user)
_gs.create_branch(
await _gs.create_branch(
dashboard_id, branch_data.name, branch_data.from_branch
)
return {"status": "success"}
@@ -253,7 +253,7 @@ async def checkout_branch(
dashboard_id = await _resolve_dashboard_id_from_ref(
dashboard_ref, config_manager, env_id
)
_gs.checkout_branch(dashboard_id, checkout_data.name)
await _gs.checkout_branch(dashboard_id, checkout_data.name)
return {"status": "success"}
except HTTPException:
raise