Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
acharneski committed Dec 1, 2024
1 parent 329bbcf commit d59fed1
Show file tree
Hide file tree
Showing 148 changed files with 978 additions and 206 deletions.
34 changes: 20 additions & 14 deletions webapp/package.json
Original file line number Diff line number Diff line change
@@ -1,40 +1,46 @@
{
"name": "chat-app",
"name": "skyenet-ui",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/free-solid-svg-icons": "^6.7.1",
"@fortawesome/react-fontawesome": "^0.2.2",
"@reduxjs/toolkit": "^1.9.7",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"dompurify": "^3.2.1",
"mermaid": "^10.0.0",
"@reduxjs/toolkit": "^2.4.0",
"express": "^4.21.1",
"cors": "^2.8.5",
"http-proxy-middleware": "^3.0.3",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"dompurify": "^3.2.2",
"mermaid": "^11.4.1",
"prismjs": "^1.29.0",
"prismjs-components-loader": "^3.0.1",
"qrcode-generator": "^1.4.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-redux": "^8.1.3",
"react-router-dom": "^6.28.0",
"react-redux": "^9.1.2",
"react-router-dom": "^7.0.1",
"react-scripts": "5.0.1",
"styled-components": "^5.3.11",
"web-vitals": "^2.1.4"
"styled-components": "^6.1.13",
"web-vitals": "^4.2.4"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@types/dompurify": "^3.2.0",
"@types/cors": "^2.8.17",
"concurrently": "^9.1.0",
"@types/node": "^22.10.1",
"@types/prismjs": "^1.26.3",
"@types/prismjs": "^1.26.5",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/react-redux": "^7.1.34",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.34",
"cross-env": "^7.0.3",
"eslint": "^8.0.0",
"typescript": "^4.9.5"
"eslint": "^9.16.0",
"typescript": "^5.7.2",
"@typescript-eslint/parser": "^8.16.0"
},
"scripts": {
"start": "cross-env NODE_ENV='development' react-scripts start",
Expand Down
5 changes: 2 additions & 3 deletions webapp/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import ErrorBoundary from './components/ErrorBoundary/ErrorBoundary';
import ErrorFallback from './components/ErrorBoundary/ErrorFallback';
import './App.css';
import websocket from './services/websocket';
import {GlobalStyles} from './styles/GlobalStyles';
import { GlobalStyles } from './styles/GlobalStyles';
import ChatInterface from './components/ChatInterface';
import ThemeProvider from './themes/ThemeProvider';
import {Menu} from "./components/Menu/Menu";
Expand Down Expand Up @@ -87,10 +87,9 @@ const App: React.FC = () => {
return (
<ThemeProvider>
{(() => {
console.debug(`${LOG_PREFIX} Rendering ThemeProvider`);
console.debug(`${LOG_PREFIX} Rendering ThemeProvider with theme`);
return (
<>
<GlobalStyles/>
<div className={`App`}>
<Menu/>
<ChatInterface
Expand Down
4 changes: 2 additions & 2 deletions webapp/src/hooks/useModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export const useModal = () => {
const getModalUrl = (endpoint: string) => {
console.log('[Modal] Constructing modal URL for endpoint:', endpoint);
const protocol = window.location.protocol;
const host = (process.env.NODE_ENV === 'development' ? config.url : null) || window.location.hostname;
const port = (process.env.NODE_ENV === 'development' ? config.port : null) || window.location.port;
const host = window.location.hostname;
const port = window.location.port;
// Handle endpoints that already have query parameters
const separator = endpoint.includes('?') ? '&' : '?';
const url = `${protocol}//${host}:${port}/${endpoint}${separator}sessionId=${WebSocketService.getSessionId()}`;
Expand Down
56 changes: 46 additions & 10 deletions webapp/src/services/appConfig.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,89 @@
import {store} from '../store';
import {logger} from '../utils/logger';
import {setAppInfo} from '../store/slices/configSlice';
const LOG_PREFIX = '[AppConfig]';

const BASE_API_URL = process.env.REACT_APP_API_URL || window.location.origin;


export const fetchAppConfig = async (sessionId: string) => {
try {
logger.info('Fetching app config for session:', sessionId);
logger.info(`${LOG_PREFIX} Fetching app config:`, {
sessionId,
baseUrl: BASE_API_URL
});

const url = new URL('/appInfo', BASE_API_URL);
url.searchParams.append('session', sessionId);

let response: Response;
// Add error handling for failed requests

try {
response = await fetch(url.toString(), {
headers: {
'Accept': 'application/json, text/json'
}
'Accept': 'application/json, text/json',
'Cache-Control': 'no-cache'
},
credentials: 'include'
});
} catch (networkError) {
logger.warn('Network request failed:', networkError);
logger.warn(`${LOG_PREFIX} Network request failed:`, {
error: networkError,
url: url.toString()
});
// Return default config for development
if (process.env.NODE_ENV === 'development') {
const defaultConfig = {
applicationName: 'Chat App (Offline)',
singleInput: false,
stickyInput: true,
loadImages: true,
showMenubar: true
};
store.dispatch(setAppInfo(defaultConfig));
return defaultConfig;
}
return null;
}

if (!response.ok) {
logger.warn(`API returned error status: ${response.status}`);
logger.warn(`${LOG_PREFIX} API error response:`, {
status: response.status,
statusText: response.statusText,
url: url.toString()
});
const errorText = await response.text();
logger.debug(`${LOG_PREFIX} Error response body:`, errorText);
return null;
}

const contentType = response.headers.get('content-type');
if (!contentType || (!contentType.includes('application/json') && !contentType.includes('text/json'))) {
throw new Error(`Invalid content type: ${contentType}`);
logger.error(`${LOG_PREFIX} Invalid content type:`, {
contentType,
url: url.toString()
});
throw new Error(`Invalid content type received: ${contentType}`);
}


const data = await response.json();
if (!data || typeof data !== 'object') {
logger.error(`${LOG_PREFIX} Invalid response format:`, data);
throw new Error('Invalid response format');
}

logger.info('Received app config:', data);
logger.info(`${LOG_PREFIX} Received valid config:`, data);

store.dispatch(setAppInfo(data));

return data;
} catch (error) {
logger.error('Failed to fetch app config:', {
logger.error(`${LOG_PREFIX} Config fetch failed:`, {
error,
sessionId,
url: BASE_API_URL ? `${BASE_API_URL}/appInfo` : '/api/appInfo'
url: BASE_API_URL ? `${BASE_API_URL}/appInfo` : '/appInfo',
env: process.env.NODE_ENV
});
throw error;
}
Expand Down
14 changes: 8 additions & 6 deletions webapp/src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import {configureStore} from '@reduxjs/toolkit';
import { Middleware } from '@reduxjs/toolkit';
import configReducer from './slices/configSlice';
import messageReducer from './slices/messageSlice';
import uiReducer from './slices/uiSlice';
import userReducer from './slices/userSlice';
import {Middleware} from 'redux';

// Utility function to get formatted timestamp
const getTimestamp = () => new Date().toISOString().split('T')[1].slice(0, -1);

// Custom middleware for logging actions and state changes
const logger: Middleware = (store) => (next) => (action) => {
const logger: Middleware = (store) => (next) => (action: unknown) => {
const timestamp = getTimestamp();
console.group(`%c Redux Action: ${action.type} @ ${timestamp}`, 'color: #8833FF; font-weight: bold;');
const actionObj = action as any;
console.group(`%c Redux Action: ${actionObj.type} @ ${timestamp}`, 'color: #8833FF; font-weight: bold;');
// Log previous state
console.log('%c Previous State:', 'color: #9E9E9E; font-weight: bold;', store.getState());
// Log action with different styling
console.log('%c Action:', 'color: #00BCD4; font-weight: bold;', {
type: action.type,
payload: action.payload,
meta: action.meta,
type: actionObj.type,
payload: actionObj.payload,
meta: actionObj.meta,
});

const result = next(action);
Expand Down
42 changes: 14 additions & 28 deletions webapp/src/styles/GlobalStyles.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,35 @@
import {createGlobalStyle, DefaultTheme} from 'styled-components';
import {createGlobalStyle} from 'styled-components';
import type {DefaultTheme} from 'styled-components';

// Enhanced logging function with timestamp
const logStyleChange = (component: string, property: string, value: any) => {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] GlobalStyles: ${component} - ${property}:`, value);
};

export const GlobalStyles = createGlobalStyle<{ theme: DefaultTheme }>`
const GlobalStyles = createGlobalStyle<{ theme: DefaultTheme; }>`
/* Theme CSS variables */
:root {
/* Add theme variables */
--theme-background: ${({theme}) => theme.colors.background};
--theme-text: ${({theme}) => theme.colors.text.primary};
--theme-surface: ${({theme}) => theme.colors.surface};
--theme-border: ${({theme}) => theme.colors.border};
--theme-primary: ${({theme}) => theme.colors.primary};
/* Theme variables are now set dynamically in ThemeProvider */
}
/* Override Prism.js theme colors to match current theme */
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: ${({theme}) => theme.colors.text.secondary};
color: var(--theme-text-secondary);
}
.token.punctuation {
color: ${({theme}) => theme.colors.text.primary};
color: var(--theme-text);
}
.token.property,
.token.tag,
.token.constant,
.token.symbol {
color: ${({theme}) => theme.colors.primary};
color: var(--theme-primary);
}
.token.boolean,
Expand Down Expand Up @@ -100,23 +97,11 @@ export const GlobalStyles = createGlobalStyle<{ theme: DefaultTheme }>`
}
body {
font-family: ${({theme}: { theme: DefaultTheme }) => {
logStyleChange('body', 'font-family', theme.typography.fontFamily);
return theme.typography.fontFamily;
}};
background-color: ${({theme}: { theme: DefaultTheme }) => {
logStyleChange('body', 'background-color', theme.colors.background);
return theme.colors.background;
}};
color: ${({theme}: { theme: DefaultTheme }) => {
logStyleChange('body', 'color', theme.colors.text.primary);
return theme.colors.text.primary;
}};
font-family: var(--theme-font-family);
background-color: var(--theme-background);
color: var(--theme-text);
line-height: 1.5;
font-size: ${({theme}: { theme: DefaultTheme }) => {
logStyleChange('body', 'font-size', theme.typography.fontSize.md);
return theme.typography.fontSize.md;
}};
font-size: var(--theme-font-size-md);
}
.chat-input {
Expand Down Expand Up @@ -192,4 +177,5 @@ export const GlobalStyles = createGlobalStyle<{ theme: DefaultTheme }>`
transform: translateY(0);
box-shadow: ${({theme}) => theme.shadows.medium};
}
`;
`;
export { GlobalStyles };
15 changes: 8 additions & 7 deletions webapp/src/themes/ThemeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {useSelector} from 'react-redux';
import {RootState} from '../store';
import {logThemeChange, ThemeName, themes} from './themes';
import Prism from 'prismjs';
import {GlobalStyles} from '../styles/GlobalStyles';

interface ThemeProviderProps {
children: React.ReactNode;
Expand Down Expand Up @@ -50,12 +51,9 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({children}) => {
// Add theme CSS variables to root
styleEl.textContent = `
:root {
--theme-background: ${themes[currentTheme].colors.background};
--theme-text: ${themes[currentTheme].colors.text.primary};
--theme-surface: ${themes[currentTheme].colors.surface};
--theme-border: ${themes[currentTheme].colors.border};
--theme-primary: ${themes[currentTheme].colors.primary};
--theme-code-font: ${themes[currentTheme].typography.console.fontFamily};
--theme-text-secondary: ${themes[currentTheme].colors.text.secondary};
--theme-font-family: ${themes[currentTheme].typography.fontFamily};
--theme-font-size-md: ${themes[currentTheme].typography.fontSize.md};
}
/* Theme-specific message content styles */
.message-content {
Expand Down Expand Up @@ -151,7 +149,10 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({children}) => {
);
}

return <StyledThemeProvider theme={theme}>{children}</StyledThemeProvider>;
return (
<StyledThemeProvider theme={theme}>
<GlobalStyles theme={theme} />{children}
</StyledThemeProvider>);
};

// Log available themes on module load
Expand Down
11 changes: 8 additions & 3 deletions webapp/src/types/qrcode.d.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
declare module 'qrcode-generator' {
declare module "qrcode-generator" {
export interface QRCode {
addData(data: string): void;

make(): void;
createImgTag(cellSize?: number, margin?: number): string;

createDataURL(cellSize?: number, margin?: number): string;

createSvgTag(cellSize?: number, margin?: number): string;
createASCII(cellSize?: number, margin?: number): string;
getModuleCount(): number;
isDark(row: number, col: number): boolean;
}

export interface QRCodeGenerator {
TypeNumber: number;
QRCode: QRCode;
TypeNumber: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 40;
ErrorCorrectionLevel: {
L: string;
M: string;
Q: string;
H: string;
};

(type?: number, errorCorrectionLevel?: string): QRCode;
(typeNumber?: number, errorCorrectionLevel?: string): QRCode;
}

const qrcode: QRCodeGenerator;
Expand Down
2 changes: 1 addition & 1 deletion webapp/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"target": "es6",
"lib": ["dom", "dom.iterable", "esnext"],
"types": ["node", "react", "react-dom", "styled-components", "qrcode-generator"],
"types": ["node", "react", "react-dom", "styled-components"],
"typeRoots": ["./node_modules/@types", "./src/types"],
"allowJs": true,
"skipLibCheck": true,
Expand Down
Loading

0 comments on commit d59fed1

Please sign in to comment.