Skip to content

Commit 0c23064

Browse files
author
Lasim
committed
chore(frontend): update team selection logic and storage integration
1 parent abeeca3 commit 0c23064

File tree

5 files changed

+232
-20
lines changed

5 files changed

+232
-20
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/frontend/src/components/AppSidebar.vue

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,36 @@ const fetchTeams = async (forceRefresh = false) => {
128128
try {
129129
teamsLoading.value = true; teamsError.value = '';
130130
const userTeams = await TeamService.getUserTeams(forceRefresh); teams.value = userTeams;
131-
if (userTeams.length > 0) { selectedTeam.value = userTeams[0]; }
131+
132+
// Initialize selected team from storage or fallback to default
133+
if (userTeams.length > 0) {
134+
const storedTeamId = eventBus.getState<string>('selected_team_id')
135+
136+
if (storedTeamId) {
137+
// Try to find the stored team in available teams
138+
const storedTeam = userTeams.find(team => team.id === storedTeamId)
139+
if (storedTeam) {
140+
selectedTeam.value = storedTeam
141+
} else {
142+
// Stored team not found, fallback to default team
143+
const defaultTeam = userTeams.find(team => team.is_default) || userTeams[0]
144+
selectedTeam.value = defaultTeam
145+
eventBus.setState('selected_team_id', defaultTeam.id)
146+
}
147+
} else {
148+
// No stored team, use default team
149+
const defaultTeam = userTeams.find(team => team.is_default) || userTeams[0]
150+
selectedTeam.value = defaultTeam
151+
eventBus.setState('selected_team_id', defaultTeam.id)
152+
}
153+
}
132154
} catch (error) { console.error('Error fetching teams:', error); teamsError.value = error instanceof Error ? error.message : 'Failed to load teams'; } finally { teamsLoading.value = false; }
133155
}
134156
135157
const selectTeam = (team: Team) => {
136158
selectedTeam.value = team
159+
// Store team selection in persistent storage
160+
eventBus.setState('selected_team_id', team.id)
137161
// Emit global event for team selection
138162
eventBus.emit('team-selected', { teamId: team.id, teamName: team.name })
139163
}

services/frontend/src/composables/useEventBus.ts

Lines changed: 152 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,162 @@ export type EventBusEvents = {
3030
'settings-updated': void
3131
'settings-group-updated': { groupId: string }
3232
'settings-connection-tested': { groupId: string; success: boolean; message: string }
33+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
34+
'storage-changed': { key: string; oldValue: any; newValue: any }
35+
}
36+
37+
// Storage configuration
38+
const STORAGE_CONFIG = {
39+
prefix: 'deploystack_',
40+
keys: {
41+
SELECTED_TEAM_ID: 'selected_team_id',
42+
}
43+
}
44+
45+
// Enhanced event bus with storage capabilities
46+
interface EnhancedEventBus extends Emitter<EventBusEvents> {
47+
setState<T>(key: string, value: T): void
48+
getState<T>(key: string, defaultValue?: T): T | null
49+
clearState(key: string): void
50+
hasState(key: string): boolean
51+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
52+
getAllState(): Record<string, any>
53+
clearAllState(): void
54+
}
55+
56+
// Storage utility functions
57+
function getStorageKey(key: string): string {
58+
return `${STORAGE_CONFIG.prefix}${key}`
59+
}
60+
61+
function safeJsonParse<T>(value: string | null, defaultValue?: T): T | null {
62+
if (value === null) return defaultValue ?? null
63+
try {
64+
return JSON.parse(value)
65+
} catch {
66+
return defaultValue ?? null
67+
}
68+
}
69+
70+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
71+
function safeJsonStringify(value: any): string {
72+
try {
73+
return JSON.stringify(value)
74+
} catch {
75+
return String(value)
76+
}
3377
}
3478

35-
export function useEventBus() {
79+
export function useEventBus(): EnhancedEventBus {
3680
const emitter = inject<Emitter<EventBusEvents>>('emitter')
3781
if (!emitter) {
3882
throw new Error('Event bus not provided. Make sure to provide the emitter in main.ts')
3983
}
40-
return emitter
84+
85+
// Add storage methods to the emitter
86+
const enhancedEmitter = emitter as EnhancedEventBus
87+
88+
// Set state in localStorage
89+
enhancedEmitter.setState = function<T>(key: string, value: T): void {
90+
const storageKey = getStorageKey(key)
91+
const oldValue = safeJsonParse(localStorage.getItem(storageKey))
92+
93+
try {
94+
localStorage.setItem(storageKey, safeJsonStringify(value))
95+
96+
// Emit storage change event
97+
this.emit('storage-changed', { key, oldValue, newValue: value })
98+
} catch (error) {
99+
console.error(`Failed to set storage for key "${key}":`, error)
100+
}
101+
}
102+
103+
// Get state from localStorage
104+
enhancedEmitter.getState = function<T>(key: string, defaultValue?: T): T | null {
105+
const storageKey = getStorageKey(key)
106+
107+
try {
108+
const value = localStorage.getItem(storageKey)
109+
return safeJsonParse<T>(value, defaultValue)
110+
} catch (error) {
111+
console.error(`Failed to get storage for key "${key}":`, error)
112+
return defaultValue ?? null
113+
}
114+
}
115+
116+
// Clear specific state
117+
enhancedEmitter.clearState = function(key: string): void {
118+
const storageKey = getStorageKey(key)
119+
const oldValue = safeJsonParse(localStorage.getItem(storageKey))
120+
121+
try {
122+
localStorage.removeItem(storageKey)
123+
124+
// Emit storage change event
125+
this.emit('storage-changed', { key, oldValue, newValue: null })
126+
} catch (error) {
127+
console.error(`Failed to clear storage for key "${key}":`, error)
128+
}
129+
}
130+
131+
// Check if state exists
132+
enhancedEmitter.hasState = function(key: string): boolean {
133+
const storageKey = getStorageKey(key)
134+
135+
try {
136+
return localStorage.getItem(storageKey) !== null
137+
} catch (error) {
138+
console.error(`Failed to check storage for key "${key}":`, error)
139+
return false
140+
}
141+
}
142+
143+
// Get all stored state
144+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
145+
enhancedEmitter.getAllState = function(): Record<string, any> {
146+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
147+
const result: Record<string, any> = {}
148+
149+
try {
150+
for (let i = 0; i < localStorage.length; i++) {
151+
const key = localStorage.key(i)
152+
if (key && key.startsWith(STORAGE_CONFIG.prefix)) {
153+
const cleanKey = key.replace(STORAGE_CONFIG.prefix, '')
154+
const value = localStorage.getItem(key)
155+
result[cleanKey] = safeJsonParse(value)
156+
}
157+
}
158+
} catch (error) {
159+
console.error('Failed to get all storage:', error)
160+
}
161+
162+
return result
163+
}
164+
165+
// Clear all stored state
166+
enhancedEmitter.clearAllState = function(): void {
167+
try {
168+
const keysToRemove: string[] = []
169+
170+
for (let i = 0; i < localStorage.length; i++) {
171+
const key = localStorage.key(i)
172+
if (key && key.startsWith(STORAGE_CONFIG.prefix)) {
173+
keysToRemove.push(key)
174+
}
175+
}
176+
177+
keysToRemove.forEach(key => {
178+
const cleanKey = key.replace(STORAGE_CONFIG.prefix, '')
179+
const oldValue = safeJsonParse(localStorage.getItem(key))
180+
localStorage.removeItem(key)
181+
182+
// Emit storage change event for each cleared key
183+
this.emit('storage-changed', { key: cleanKey, oldValue, newValue: null })
184+
})
185+
} catch (error) {
186+
console.error('Failed to clear all storage:', error)
187+
}
188+
}
189+
190+
return enhancedEmitter
41191
}

services/frontend/src/views/Credentials.vue

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,39 @@ const userPermissions = ref<string[]>([])
4343
const searchQuery = ref('')
4444
const deleteSuccessMessage = ref<string | null>(null)
4545
46-
// Team context (same pattern as teams page)
46+
// Team context using event bus storage
4747
const selectedTeam = ref<Team | null>(null)
4848
49+
// Initialize selected team from storage
50+
const initializeSelectedTeam = async () => {
51+
try {
52+
const userTeams = await TeamService.getUserTeams()
53+
if (userTeams.length > 0) {
54+
const storedTeamId = eventBus.getState<string>('selected_team_id')
55+
56+
if (storedTeamId) {
57+
// Try to find the stored team in available teams
58+
const storedTeam = userTeams.find(team => team.id === storedTeamId)
59+
if (storedTeam) {
60+
selectedTeam.value = storedTeam
61+
} else {
62+
// Stored team not found, fallback to default team
63+
const defaultTeam = userTeams.find(team => team.is_default) || userTeams[0]
64+
selectedTeam.value = defaultTeam
65+
eventBus.setState('selected_team_id', defaultTeam.id)
66+
}
67+
} else {
68+
// No stored team, use default team
69+
const defaultTeam = userTeams.find(team => team.is_default) || userTeams[0]
70+
selectedTeam.value = defaultTeam
71+
eventBus.setState('selected_team_id', defaultTeam.id)
72+
}
73+
}
74+
} catch (error) {
75+
console.error('Error initializing selected team:', error)
76+
}
77+
}
78+
4979
// Handle team selection from sidebar
5080
const handleTeamSelected = async (data: { teamId: string; teamName: string }) => {
5181
// Find the full team object with role information
@@ -67,18 +97,6 @@ const handleTeamSelected = async (data: { teamId: string; teamName: string }) =>
6797
}
6898
}
6999
70-
// Initialize selected team from sidebar teams
71-
const initializeSelectedTeam = async () => {
72-
try {
73-
const userTeams = await TeamService.getUserTeams()
74-
if (userTeams.length > 0) {
75-
selectedTeam.value = userTeams[0] // Default to first team
76-
}
77-
} catch (error) {
78-
console.error('Error initializing selected team:', error)
79-
}
80-
}
81-
82100
// Check user permissions
83101
const checkPermissions = async () => {
84102
try {

services/frontend/src/views/teams/index.vue

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ const handleSwitchTeam = (teamId: string) => {
4242
const team = teams.value.find(t => t.id === teamId)
4343
if (team) {
4444
selectedTeam.value = team
45+
// Store team selection in persistent storage
46+
eventBus.setState('selected_team_id', team.id)
4547
// Emit global event for team selection to update sidebar
4648
eventBus.emit('team-selected', { teamId: team.id, teamName: team.name })
4749
}
@@ -86,12 +88,30 @@ const filteredTeams = computed(() => {
8688
)
8789
})
8890
89-
// Initialize selected team from sidebar teams
91+
// Initialize selected team from storage
9092
const initializeSelectedTeam = async () => {
9193
try {
9294
const userTeams = await TeamService.getUserTeams()
9395
if (userTeams.length > 0) {
94-
selectedTeam.value = userTeams[0] // Default to first team
96+
const storedTeamId = eventBus.getState<string>('selected_team_id')
97+
98+
if (storedTeamId) {
99+
// Try to find the stored team in available teams
100+
const storedTeam = userTeams.find(team => team.id === storedTeamId)
101+
if (storedTeam) {
102+
selectedTeam.value = storedTeam
103+
} else {
104+
// Stored team not found, fallback to default team
105+
const defaultTeam = userTeams.find(team => team.is_default) || userTeams[0]
106+
selectedTeam.value = defaultTeam
107+
eventBus.setState('selected_team_id', defaultTeam.id)
108+
}
109+
} else {
110+
// No stored team, use default team
111+
const defaultTeam = userTeams.find(team => team.is_default) || userTeams[0]
112+
selectedTeam.value = defaultTeam
113+
eventBus.setState('selected_team_id', defaultTeam.id)
114+
}
95115
}
96116
} catch (error) {
97117
console.error('Error initializing selected team:', error)

0 commit comments

Comments
 (0)