Skip to content

Commit

Permalink
✨ Add new features and update routes
Browse files Browse the repository at this point in the history
- Enabled service worker generation in rollup.config.js.
- Deleted the "About" page (page-about.ts).
- Enhanced page-home.ts with new text input, image upload, and navigation functionalities.
- Added support for session storage and routing to the chat page after interactions.
- Updated routes.ts to replace the "About" page with "User" and "Chat" pages.
- Added new imports and lazy loading for the updated routes.
Improved overall structure and modularity of the project.
  • Loading branch information
joycexjl committed Jan 4, 2025
1 parent 802ff43 commit 606638f
Show file tree
Hide file tree
Showing 7 changed files with 551 additions and 58 deletions.
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { black, blue, bgWhite } from 'picocolors';

const NODE_ENV = process.env.NODE_ENV || 'development';
const DIST_PATH = 'server/dist/';
const GENERATE_SERVICE_WORKER = false;
const GENERATE_SERVICE_WORKER = true;

const absoluteBaseUrl =
NODE_ENV === 'production'
Expand Down
146 changes: 146 additions & 0 deletions src/components/network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/**
* Network utilities for communicating with the backend server
*/

const BASE_URL = 'https://druid.eecs.umich.edu';
const API_ENDPOINTS = {
auth: `${BASE_URL}/auth`,
nlip: `${BASE_URL}/nlip`,
upload: `${BASE_URL}/upload`,
};

interface Message {
format: 'text' | 'binary';
subformat: string;
content: string;
}

interface NLIPRequest {
format: 'text';
subformat: string;
content: string;
submessages?: Message[];
}

interface APIResponse {
response: string;
// Add other response fields if needed
}

/**
* Get authentication URL for a specific provider
*/
export async function getAuthUrl(): Promise<string> {
try {
const response = await fetch(API_ENDPOINTS.auth);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data.url;
} catch (error) {
console.error('Error getting auth URL:', error);
throw error;
}
}

/**
* Send a text message to the NLIP endpoint
*/
export async function sendTextMessage(text: string): Promise<string> {
const request: NLIPRequest = {
format: 'text',
subformat: 'english',
content: text,
};

try {
const response = await fetch(API_ENDPOINTS.nlip, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data: APIResponse = await response.json();
return data.response;
} catch (error) {
console.error('Error sending text message:', error);
throw error;
}
}

/**
* Send an image with an optional prompt to the NLIP endpoint
*/
export async function sendImageMessage(
prompt: string,
base64Image: string,
mimeType: string
): Promise<string> {
// Extract the image format from the MIME type (e.g., 'image/jpeg' -> 'jpeg')
const imageFormat = mimeType.split('/')[1];

const request: NLIPRequest = {
format: 'text',
subformat: 'english',
content: prompt || 'Describe this picture',
submessages: [
{
format: 'binary',
subformat: imageFormat,
content: base64Image,
},
],
};

try {
const response = await fetch(API_ENDPOINTS.nlip, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data: APIResponse = await response.json();
return data.response;
} catch (error) {
console.error('Error sending image message:', error);
throw error;
}
}

/**
* Upload a file using form data
*/
export async function uploadFile(file: File): Promise<string> {
const formData = new FormData();
formData.append('file', file);

try {
const response = await fetch(API_ENDPOINTS.upload, {
method: 'POST',
body: formData,
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json();
return data.url; // Assuming the server returns the URL of the uploaded file
} catch (error) {
console.error('Error uploading file:', error);
throw error;
}
}
42 changes: 0 additions & 42 deletions src/pages/page-about.ts

This file was deleted.

152 changes: 152 additions & 0 deletions src/pages/page-chat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/**
* Copyright (c) IBM, Corp. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import { html, css } from 'lit';
import { customElement, property } from 'lit/decorators.js';

import { PageElement } from '../helpers/page-element.js';

@customElement('page-chat')
export class PageChat extends PageElement {
@property({ type: String }) userPrompt = '';
@property({ type: String }) aiResponse = '';

connectedCallback(): void {
super.connectedCallback?.();
// Load chat data from sessionStorage
const chatData = sessionStorage.getItem('chatData');
if (chatData) {
const { userPrompt, aiResponse } = JSON.parse(chatData);
this.userPrompt = userPrompt;
this.aiResponse = aiResponse;
// Clear the data after loading
sessionStorage.removeItem('chatData');
}
}

static styles = css`
@supports (padding: max(0px)) {
.toolbar {
height: calc(60px + env(safe-area-inset-bottom));
padding-bottom: max(env(safe-area-inset-bottom), 0px);
}
} :host {
display: block;
min-height: 100vh;
padding-bottom: 60px;
background: #f5f5f7;
}
.chat-container {
max-width: min(90vw, 800px);
margin: 0 auto;
padding: clamp(1rem, 5vw, 2rem);
}
.message {
margin-bottom: 1.5rem;
padding: 1rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgb(0 0 0 / 10%);
}
.user-message {
margin-left: 2rem;
background: #007bff;
color: white;
}
.ai-message {
margin-right: 2rem;
background: white;
color: #333;
}
.message-header {
margin-bottom: 0.5rem;
font-weight: 500;
font-size: 0.9rem;
opacity: 0.8;
}
.message-content {
line-height: 1.5;
}
/* Bottom Toolbar Styles */
.toolbar {
position: fixed;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
display: flex;
justify-content: space-around;
align-items: center;
height: 60px;
padding: 0 env(safe-area-inset-right) env(safe-area-inset-bottom)
env(safe-area-inset-left);
background: #fff;
box-shadow: 0 -2px 10px rgb(0 0 0 / 10%);
}
.toolbar a {
display: flex;
flex-direction: column;
align-items: center;
padding: 8px;
color: #666;
font-size: 0.75rem;
text-decoration: none;
user-select: none;
transition: color 0.2s;
-webkit-tap-highlight-color: transparent;
}
.toolbar svg {
width: 24px;
height: 24px;
margin-bottom: 4px;
}
`;

render() {
return html`
<div class="chat-container">
<div class="message user-message">
<div class="message-header">You</div>
<div class="message-content">${this.userPrompt}</div>
</div>
<div class="message ai-message">
<div class="message-header">AI</div>
<div class="message-content">${this.aiResponse}</div>
</div>
</div>
<nav class="toolbar">
<a href="/">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2L2 12h3v8h6v-6h2v6h6v-8h3L12 2zm0 2.84L19.5 12h-1.5v8h-4v-6H10v6H6v-8H4.5L12 4.84z"
/>
</svg>
Home
</a>
<a href="/user">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0-6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm0 7c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4zm6 5H6v-.99c.2-.72 3.3-2.01 6-2.01s5.8 1.29 6 2v1z"
/>
</svg>
User
</a>
</nav>
`;
}
}
Loading

0 comments on commit 606638f

Please sign in to comment.