oop
This commit is contained in:
parent
a59b6a5cfd
commit
dcea70fc17
8 changed files with 1013 additions and 75 deletions
827
package-lock.json
generated
827
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -18,6 +18,9 @@
|
||||||
"@lit/localize": "^0.12.2",
|
"@lit/localize": "^0.12.2",
|
||||||
"@shoelace-style/shoelace": "^2.18.0",
|
"@shoelace-style/shoelace": "^2.18.0",
|
||||||
"@thepassle/app-tools": "^0.9.12",
|
"@thepassle/app-tools": "^0.9.12",
|
||||||
|
"axios": "^1.7.7",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"express": "^4.21.1",
|
||||||
"lit": "^3.2.1",
|
"lit": "^3.2.1",
|
||||||
"nostr-tools": "^2.10.1",
|
"nostr-tools": "^2.10.1",
|
||||||
"urlpattern-polyfill": "^10.0.0",
|
"urlpattern-polyfill": "^10.0.0",
|
||||||
|
@ -26,6 +29,7 @@
|
||||||
"workbox-precaching": "^7.3.0"
|
"workbox-precaching": "^7.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"concurrently": "^9.1.0",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.6.3",
|
||||||
"vite": "^5.4.11",
|
"vite": "^5.4.11",
|
||||||
"vite-plugin-pwa": "^0.20.5"
|
"vite-plugin-pwa": "^0.20.5"
|
||||||
|
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
@ -70,7 +70,7 @@ export class AppHeader extends LitElement {
|
||||||
//is there a stored pubkey in localStorage already?
|
//is there a stored pubkey in localStorage already?
|
||||||
const storedPubkey = localStorage.getItem('pubkey');
|
const storedPubkey = localStorage.getItem('pubkey');
|
||||||
if (storedPubkey) {
|
if (storedPubkey) {
|
||||||
this.isSignedIn = true;
|
this.isSignedIn = false;
|
||||||
this.fetchProfileMetadata(storedPubkey);
|
this.fetchProfileMetadata(storedPubkey);
|
||||||
} else {
|
} else {
|
||||||
// Show guest view by default
|
// Show guest view by default
|
||||||
|
@ -81,7 +81,7 @@ export class AppHeader extends LitElement {
|
||||||
// Set initial values for guest view
|
// Set initial values for guest view
|
||||||
this.nostrAddy = '';
|
this.nostrAddy = '';
|
||||||
this.bio = 'Welcome, guest! Please sign in with a browser extension to view your profile.';
|
this.bio = 'Welcome, guest! Please sign in with a browser extension to view your profile.';
|
||||||
this.profilePic = ''; // Could be a placeholder image for guests
|
this.profilePic = '/public/assets/img/default_pfp.png'; // Could be a placeholder image for guests
|
||||||
this.isSignedIn = false;
|
this.isSignedIn = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,20 +98,27 @@ export class AppHeader extends LitElement {
|
||||||
], {
|
], {
|
||||||
onevent: (event) => {
|
onevent: (event) => {
|
||||||
const profileData = JSON.parse(event.content);
|
const profileData = JSON.parse(event.content);
|
||||||
this.profilePic = profileData.picture || '';
|
this.profilePic = profileData.picture || '/assets/img/default_pfp.png';
|
||||||
this.nostrAddy = profileData.nip05 || '';
|
this.nostrAddy = profileData.nip05 || 'no addy available';
|
||||||
this.bio = profileData.about || '';
|
this.bio = profileData.about || 'bio not available';
|
||||||
|
|
||||||
this.dispatchEvent(new CustomEvent('profile-updated' , {
|
this.dispatchEvent(new CustomEvent('profile-updated' , {
|
||||||
detail: { nostrAddy: this.nostrAddy, bio: this.bio, profilePic: this.profilePic },
|
detail: { nostrAddy: this.nostrAddy, bio: this.bio, profilePic: this.profilePic },
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
composed: true
|
composed: true
|
||||||
}));
|
}));
|
||||||
|
console.log('Profile updated event dispatched:', { nostrAddy: this.nostrAddy, bio: this.bio, profilePic: this.profilePic });
|
||||||
|
|
||||||
},
|
},
|
||||||
oneose: () => {
|
oneose: () => {
|
||||||
sub.close();
|
sub.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('Failed to fetch profile metadata:', error);
|
||||||
|
this.profilePic = '/assets/img/default_pfp.png';
|
||||||
|
this.nostrAddy = 'failed to fetch address';
|
||||||
|
this.bio = 'failed to fetch profile'
|
||||||
}
|
}
|
||||||
|
|
||||||
async signInWithNostr() {
|
async signInWithNostr() {
|
||||||
|
@ -126,6 +133,7 @@ export class AppHeader extends LitElement {
|
||||||
await this.fetchProfileMetadata(userPubkey);
|
await this.fetchProfileMetadata(userPubkey);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to sign in:', error);
|
console.error('Failed to sign in:', error);
|
||||||
|
this.isSignedIn = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert('Nostr extension not detected. Please install a Nostr extension.');
|
alert('Nostr extension not detected. Please install a Nostr extension.');
|
||||||
|
@ -134,8 +142,11 @@ export class AppHeader extends LitElement {
|
||||||
|
|
||||||
signOut() {
|
signOut() {
|
||||||
// clear pubkey from localStorage and reset to guest view
|
// clear pubkey from localStorage and reset to guest view
|
||||||
localStorage.removeItem('pubKey');
|
localStorage.removeItem('pubkey');
|
||||||
this.displayGuestView();
|
this.displayGuestView();
|
||||||
|
|
||||||
|
this.isSignedIn = false;
|
||||||
|
|
||||||
console.log('signed out')
|
console.log('signed out')
|
||||||
|
|
||||||
this.dispatchEvent( new CustomEvent('user-signed-out', {
|
this.dispatchEvent( new CustomEvent('user-signed-out', {
|
||||||
|
@ -157,7 +168,7 @@ export class AppHeader extends LitElement {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<sl-button variant="primary" @click="${this.isSignedIn ? this.signOut : this.signInWithNostr}">
|
<sl-button variant="primary" @click="${this.isSignedIn ? this.signOut : this.signInWithNostr}">
|
||||||
${this.isSignedIn ? 'Sign out' : 'Sign in with Nostr'}
|
${this.isSignedIn ? 'Sign out' : 'Sign in'}
|
||||||
|
|
||||||
</sl-button>
|
</sl-button>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { property, customElement } from 'lit/decorators.js';
|
||||||
import { resolveRouterPath } from '../router';
|
import { resolveRouterPath } from '../router';
|
||||||
import { Relay } from 'nostr-tools';
|
import { Relay } from 'nostr-tools';
|
||||||
import { WindowNostr } from 'nostr-tools/nip07';
|
import { WindowNostr } from 'nostr-tools/nip07';
|
||||||
import '../img/default_pfp.png'
|
|
||||||
|
|
||||||
import '@shoelace-style/shoelace/dist/components/card/card.js';
|
import '@shoelace-style/shoelace/dist/components/card/card.js';
|
||||||
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
||||||
|
@ -27,6 +26,7 @@ export class AppHome extends LitElement {
|
||||||
@property({ type: String }) profilePic = '';
|
@property({ type: String }) profilePic = '';
|
||||||
@property({ type: Boolean }) isSignedIn = false;
|
@property({ type: Boolean }) isSignedIn = false;
|
||||||
@property({ type: String }) publicKey = '';
|
@property({ type: String }) publicKey = '';
|
||||||
|
@property({ type: String }) updateProfileFromEvent = ''
|
||||||
|
|
||||||
|
|
||||||
static styles = [
|
static styles = [
|
||||||
|
@ -76,10 +76,11 @@ Profile Picture Container
|
||||||
*/
|
*/
|
||||||
.profile-picture-container {
|
.profile-picture-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 200px 115px;
|
grid-template-columns: 300px 150px;
|
||||||
grid-template-rows: 250px;
|
grid-template-rows: 250px;
|
||||||
grid-column-gap: 15px;
|
grid-column-gap: 15px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-picture-container p {
|
.profile-picture-container p {
|
||||||
|
@ -90,11 +91,12 @@ Profile Picture Container
|
||||||
grid-area: 1/1;
|
grid-area: 1/1;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.personal-msg {
|
.personal-msg {
|
||||||
grid-area: 1/2;
|
grid-area: 1/2;
|
||||||
margin: 0;
|
margin-top: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,9 +109,6 @@ Profile Picture Container
|
||||||
|
|
||||||
`];
|
`];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async firstUpdated() {
|
async firstUpdated() {
|
||||||
// this method is a lifecycle even in lit
|
// this method is a lifecycle even in lit
|
||||||
// for more info check out the lit docs https://lit.dev/docs/components/lifecycle/
|
// for more info check out the lit docs https://lit.dev/docs/components/lifecycle/
|
||||||
|
@ -119,29 +118,43 @@ Profile Picture Container
|
||||||
|
|
||||||
connectedCallback(): void {
|
connectedCallback(): void {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
this.addEventListener('user-signed-out', this.handlesSignOut.bind(this))
|
window.addEventListener('profile-updated', this.updateProfileFromEvent.bind(this));
|
||||||
|
const storedPubkey = localStorage.getItem('pubkey');
|
||||||
|
if (storedPubkey) {
|
||||||
|
// Manually fetch profile metadata on mount
|
||||||
|
this.nostrAddy = 'Fetching...';
|
||||||
|
this.bio = 'Fetching profile...';
|
||||||
|
this.profilePic = '/assets/img/default_pfp.png';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handlesSignOut() {
|
|
||||||
this.profilePic = '';
|
|
||||||
this.bio = '';
|
|
||||||
this.nostrAddy = 'Guest'
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnectedCallback(): void {
|
disconnectedCallback(): void {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
window.removeEventListener('profile-updated', this.updateProfileFromEvent.bind(this));
|
window.removeEventListener('profile-updated', this.updateProfileFromEvent.bind(this));
|
||||||
|
window.removeEventListener('user-signed-out', this.handlesSignOut.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProfileFromEvent(event: Event) {
|
/* updateProfileFromEvent(event: Event) {
|
||||||
|
console.log('Profile updated event received:', (event as CustomEvent).detail);
|
||||||
|
|
||||||
const detail = (event as CustomEvent).detail;
|
const detail = (event as CustomEvent).detail;
|
||||||
this.nostrAddy = detail.nostrAddy;
|
this.nostrAddy = detail.nostrAddy;
|
||||||
this.bio = detail.bio;
|
this.bio = detail.bio;
|
||||||
this.profilePic = detail.profilePic;
|
this.profilePic = detail.profilePic;
|
||||||
this.isSignedIn = true;
|
this.isSignedIn = true;
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
|
} */
|
||||||
|
|
||||||
|
handlesSignOut() {
|
||||||
|
this.profilePic = '';
|
||||||
|
this.bio = '';
|
||||||
|
this.nostrAddy = 'Guest';
|
||||||
|
this.isSignedIn = false;
|
||||||
|
this.requestUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
displayGuestView() {
|
displayGuestView() {
|
||||||
// Set initial values for guest view
|
// Set initial values for guest view
|
||||||
this.nostrAddy = '';
|
this.nostrAddy = '';
|
||||||
|
@ -151,8 +164,6 @@ handlesSignOut() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
share() {
|
share() {
|
||||||
if ((navigator as any).share) {
|
if ((navigator as any).share) {
|
||||||
(navigator as any).share({
|
(navigator as any).share({
|
||||||
|
@ -166,9 +177,6 @@ handlesSignOut() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<app-header></app-header>
|
<app-header></app-header>
|
||||||
|
@ -188,9 +196,7 @@ handlesSignOut() {
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="profile-picture-container">
|
<div class="profile-picture-container">
|
||||||
${this.profilePic
|
<img class="profile-pic" src="${this.profilePic || '/assets/img/default_pfp.png'}" alt="Profile Picture" width="200px" height="200px">
|
||||||
? html`<img class="profile-pic" src="${this.profilePic}" alt="Profile Picture" width="200px" height="200px">`
|
|
||||||
: html`<img class="profile-pic" src="img/default_pfp.png" alt="Guest Profile Picture" width="200px" height="200px">`}
|
|
||||||
|
|
||||||
<p class="personal-msg"><b>${this.bio || 'Welcome, guest! Please sign in to view your profile.'}</b></p>
|
<p class="personal-msg"><b>${this.bio || 'Welcome, guest! Please sign in to view your profile.'}</b></p>
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { LitElement, css, html } from 'lit';
|
||||||
import { property, customElement } from 'lit/decorators.js';
|
import { property, customElement } from 'lit/decorators.js';
|
||||||
import { resolveRouterPath } from '../router';
|
import { resolveRouterPath } from '../router';
|
||||||
import { Relay } from 'nostr-tools';
|
import { Relay } from 'nostr-tools';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
import '@shoelace-style/shoelace/dist/components/card/card.js';
|
import '@shoelace-style/shoelace/dist/components/card/card.js';
|
||||||
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
||||||
|
@ -16,7 +17,6 @@ export class NoteWall extends LitElement {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static styles = [
|
static styles = [
|
||||||
styles,
|
styles,
|
||||||
css`
|
css`
|
||||||
|
@ -144,6 +144,10 @@ export class NoteWall extends LitElement {
|
||||||
|
|
||||||
note = ''; // store notes
|
note = ''; // store notes
|
||||||
|
|
||||||
|
getUserLang() {
|
||||||
|
return navigator.language || 'en';
|
||||||
|
}
|
||||||
|
|
||||||
async firstUpdated() {
|
async firstUpdated() {
|
||||||
// this method is a lifecycle even in lit
|
// this method is a lifecycle even in lit
|
||||||
// for more info check out the lit docs https://lit.dev/docs/components/lifecycle/
|
// for more info check out the lit docs https://lit.dev/docs/components/lifecycle/
|
||||||
|
@ -158,40 +162,61 @@ export class NoteWall extends LitElement {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async translateText(text: string, targetLang: string) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post('https://api-free.deepl.com/v2/translate', {
|
||||||
|
text, target_lang: targetLang });
|
||||||
|
|
||||||
|
return response.data.translations[0].text; // Assuming DeepL's API structure
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error during translation:', error.response?.data || error.message);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async fetchNotes() {
|
async fetchNotes() {
|
||||||
const ifcaRelay = await Relay.connect('wss://hi.myvoiceourstory.org');
|
const ifcaRelay = await Relay.connect('wss://hi.myvoiceourstory.org');
|
||||||
const migsRelay = await Relay.connect('wss://notes.miguelalmodo.com');
|
const migsRelay = await Relay.connect('wss://notes.miguelalmodo.com');
|
||||||
console.log(`connected to ${ifcaRelay.url}`);
|
console.log(`connected to ${ifcaRelay.url}`);
|
||||||
console.log(`connected to ${migsRelay.url}`);
|
console.log(`connected to ${migsRelay.url}`);
|
||||||
const eric = 'f8d17812ce41a9b145aede4f0720050ab63607f51688832b5d78c65d620ec7d9'
|
|
||||||
const migs = 'ec965405e11a6a6186b27fa451a2ffc1396ede7883d2ea11c32fbd2c63996966'
|
|
||||||
|
|
||||||
|
|
||||||
const sub = ifcaRelay.subscribe([
|
const sub = ifcaRelay.subscribe([
|
||||||
{
|
{
|
||||||
kinds: [1], // short form notes
|
kinds: [1], // short form notes
|
||||||
limit: 20,
|
limit: 20,
|
||||||
authors: [eric]
|
|
||||||
}
|
}
|
||||||
], {
|
], {
|
||||||
onevent: (event) => {
|
onevent: async (event) => {
|
||||||
|
// Translate the note content to the user's language
|
||||||
|
const userLang = this.getUserLang();
|
||||||
|
const translatedContent = await this.translateText(event.content, userLang);
|
||||||
|
|
||||||
this.notes.push({
|
this.notes.push({
|
||||||
content: event.content,
|
content: translatedContent,
|
||||||
date: new Date(event.created_at * 1000).toLocaleDateString()
|
date: new Date(event.created_at * 1000).toLocaleDateString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
console.log(event)
|
console.log(event);
|
||||||
},
|
},
|
||||||
oneose: () => {
|
oneose: () => {
|
||||||
sub.close();
|
sub.close();
|
||||||
|
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
share() {
|
share() {
|
||||||
if ((navigator as any).share) {
|
if ((navigator as any).share) {
|
||||||
(navigator as any).share({
|
(navigator as any).share({
|
||||||
|
@ -218,17 +243,32 @@ export class NoteWall extends LitElement {
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
${this.notes.map(note => {
|
${this.notes.map(note => {
|
||||||
// Check if there's a URL in the content
|
// Extract URL from note content
|
||||||
const urlMatch = note.content.match(/https?:\/\/[^\s]+/);
|
const urlMatch = note.content.match(/https?:\/\/[^\s]+/);
|
||||||
const imageUrl = urlMatch ? urlMatch[0] : null;
|
|
||||||
const textContent = note.content.replace(urlMatch?.[0] || '', '').trim();
|
const textContent = note.content.replace(urlMatch?.[0] || '', '').trim();
|
||||||
|
|
||||||
|
// Check for YouTube links and extract video ID
|
||||||
|
const youtubeRegex = /(?:https?:\/\/(?:www\.)?youtube\.com\/watch\?v=|https?:\/\/youtu\.be\/)([a-zA-Z0-9_-]{11})/;
|
||||||
|
const youtubeMatch = urlMatch?.[0].match(youtubeRegex);
|
||||||
|
const youtubeVideoId = youtubeMatch ? youtubeMatch[1] : null;
|
||||||
|
|
||||||
|
// Construct YouTube thumbnail URL if applicable
|
||||||
|
const thumbnailUrl = youtubeVideoId
|
||||||
|
? `https://img.youtube.com/vi/${youtubeVideoId}/maxresdefault.jpg`
|
||||||
|
: null;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<tr>
|
<tr>
|
||||||
<td><h3>${note.date}</h3></td>
|
<td><h3>${note.date}</h3></td>
|
||||||
<td>
|
<td>
|
||||||
<p>${textContent}</p>
|
<p>${textContent}</p>
|
||||||
${imageUrl ? html`<img src="${imageUrl}" alt="Note image" style="max-width: 30%; height: 30%;">` : ''}
|
${thumbnailUrl
|
||||||
|
? html`<img src="${thumbnailUrl}" alt="YouTube thumbnail" style="max-width: 30%; height: 30%;">`
|
||||||
|
: urlMatch
|
||||||
|
? html`<img src="${urlMatch[0]}" alt="Note image" style="max-width: 30%; height: 30%;">`
|
||||||
|
: ''}
|
||||||
|
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
|
@ -236,6 +276,8 @@ export class NoteWall extends LitElement {
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section></main>
|
</section></main>
|
||||||
</sl-card>
|
</sl-card>
|
||||||
`;
|
`;
|
||||||
|
|
45
src/server.js
Normal file
45
src/server.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
const express = require('express');
|
||||||
|
const axios = require('axios');
|
||||||
|
const bodyParser = require('body-parser');
|
||||||
|
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
res.header('Access-Control-Allow-Origin', 'http://localhost:5176'); // Allow your frontend
|
||||||
|
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); // Allow required HTTP methods
|
||||||
|
res.header('Access-Control-Allow-Headers', 'Content-Type'); // Allow required headers
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
app.post('/translate', async (req, res) => {
|
||||||
|
const { text, target_lang } = req.body;
|
||||||
|
|
||||||
|
console.log('Received request:', { text, target_lang });
|
||||||
|
|
||||||
|
if (!text || !target_lang) {
|
||||||
|
console.error('Invalid request payload:', req.body);
|
||||||
|
return res.status(400).send('Missing text or target_lang');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const apiKey = '5e8b82a7-3595-466d-bb60-b11d5c128697:fx'; // Ensure this is set
|
||||||
|
const response = await axios.post('https://api.deepl.com/v2/translate', {
|
||||||
|
auth_key: apiKey,
|
||||||
|
text,
|
||||||
|
target_lang,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Translation API response:', response.data);
|
||||||
|
res.status(200).json(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error during translation:', error.response?.data || error.message);
|
||||||
|
res.status(500).send('Error during translation.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(3000, () => {
|
||||||
|
console.log('Server running on http://localhost:3000');
|
||||||
|
});
|
|
@ -4,6 +4,9 @@ import { VitePWA } from 'vite-plugin-pwa';
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
base: "/",
|
base: "/",
|
||||||
|
server: {
|
||||||
|
port: 5176,
|
||||||
|
},
|
||||||
build: {
|
build: {
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
assetsDir: "code",
|
assetsDir: "code",
|
||||||
|
|
Loading…
Reference in a new issue