introduced uiText.ts
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useRef, useState, type SyntheticEvent } from 'react'
|
||||
import { login } from '../../api/connections'
|
||||
import type { LoginRequest, ServiceType } from '../../types/connection'
|
||||
import { uiText } from '../../text/uiText'
|
||||
import '../ui/Modal.scss'
|
||||
|
||||
interface Props {
|
||||
@@ -44,7 +45,7 @@ export function ConnectModal({ serviceType, label, onClose, onSuccess }: Readonl
|
||||
await login(req)
|
||||
onSuccess()
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Login failed')
|
||||
setError(err instanceof Error ? err.message : uiText.connections.connectModal.loginFailed)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -53,31 +54,31 @@ export function ConnectModal({ serviceType, label, onClose, onSuccess }: Readonl
|
||||
return (
|
||||
<dialog className="modal" ref={dialogRef}>
|
||||
<div className="modal__header">
|
||||
<h2 className="modal__title" id="modal-title">Connect to {label}</h2>
|
||||
<button className="modal__close" onClick={onClose} aria-label="Close">×</button>
|
||||
<h2 className="modal__title" id="modal-title">{uiText.connections.connectModal.title(label)}</h2>
|
||||
<button className="modal__close" onClick={onClose} aria-label={uiText.modal.closeAriaLabel}>{uiText.modal.closeSymbol}</button>
|
||||
</div>
|
||||
<form className="modal__form" onSubmit={handleSubmit}>
|
||||
<div className="modal__field">
|
||||
<label className="modal__label" htmlFor="appUrl">App URL</label>
|
||||
<label className="modal__label" htmlFor="appUrl">{uiText.connections.connectModal.appUrlLabel}</label>
|
||||
<input id="appUrl" ref={firstInputRef} className="modal__input" type="url"
|
||||
placeholder="https://homebox.example.com"
|
||||
placeholder={uiText.connections.connectModal.appUrlPlaceholder}
|
||||
value={appUrl} onChange={e => setAppUrl(e.target.value)} required />
|
||||
</div>
|
||||
<div className="modal__field">
|
||||
<label className="modal__label" htmlFor="username">Username</label>
|
||||
<label className="modal__label" htmlFor="username">{uiText.connections.connectModal.usernameLabel}</label>
|
||||
<input id="username" className="modal__input" type="text"
|
||||
autoComplete="username"
|
||||
value={username} onChange={e => setUsername(e.target.value)} required />
|
||||
</div>
|
||||
<div className="modal__field">
|
||||
<label className="modal__label" htmlFor="password">Password</label>
|
||||
<label className="modal__label" htmlFor="password">{uiText.connections.connectModal.passwordLabel}</label>
|
||||
<input id="password" className="modal__input" type="password"
|
||||
autoComplete="current-password"
|
||||
value={password} onChange={e => setPassword(e.target.value)} required />
|
||||
</div>
|
||||
{error && <p className="modal__error">{error}</p>}
|
||||
<button className="modal__submit" type="submit" disabled={loading}>
|
||||
{loading ? 'Connecting…' : 'Connect'}
|
||||
{loading ? uiText.connections.connectModal.connectingButton : uiText.connections.connectModal.connectButton}
|
||||
</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ServiceCard } from "./ServiceCard"
|
||||
import { ConnectModal } from "./ConnectModal"
|
||||
import "./Dashboard.scss"
|
||||
import { SearchModal } from "../search/SearchModal"
|
||||
import { uiText } from "../../text/uiText"
|
||||
|
||||
const SERVICES = [
|
||||
{ serviceType: ServiceType.HOMEBOX, label: 'Homebox', icon: '📦' },
|
||||
@@ -32,10 +33,10 @@ export function Dashboard() {
|
||||
return (
|
||||
<div className="dashboard">
|
||||
<div className="dashboard__header">
|
||||
<h1 className="dashboard__title">Vaessl Dashboard</h1>
|
||||
<h1 className="dashboard__title">{uiText.dashboard.title}</h1>
|
||||
</div>
|
||||
|
||||
<p className="dashboard__section-label">Services</p>
|
||||
<p className="dashboard__section-label">{uiText.dashboard.servicesLabel}</p>
|
||||
<div className="dashboard__cards">
|
||||
{SERVICES.map(({ serviceType, label, icon }) => (
|
||||
<ServiceCard
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { ConnectionStatus, ServiceType } from '../../types/connection'
|
||||
import { ActionButton } from '../ui/ActionButton'
|
||||
import { uiText } from '../../text/uiText'
|
||||
import './ServiceCard.scss'
|
||||
|
||||
interface Props {
|
||||
@@ -29,20 +30,20 @@ export function ServiceCard({ serviceType: _serviceType, label, icon, status, on
|
||||
<p className="service-card__name">{label}</p>
|
||||
<p className="service-card__meta">
|
||||
<span className={`service-card__badge service-card__badge--${connected ? 'connected' : 'disconnected'}`}>
|
||||
{connected ? 'Connected' : 'Not connected'}
|
||||
{connected ? uiText.connections.serviceCard.connected : uiText.connections.serviceCard.notConnected}
|
||||
</span>
|
||||
{connected && status?.username && <span>{status.username}</span>}
|
||||
{connected && status?.expiresAt && (
|
||||
<span>· expires {formatExpiry(status.expiresAt)}</span>
|
||||
<span>{uiText.connections.serviceCard.expiresPrefix(formatExpiry(status.expiresAt) ?? '')}</span>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="service-card__actions">
|
||||
<ActionButton variant={connected ? 'disconnect' : 'connect'} onClick={connected ? onDisconnect : onConnect}>
|
||||
{connected ? 'Disconnect' : 'Connect'}
|
||||
{connected ? uiText.connections.serviceCard.disconnectButton : uiText.connections.serviceCard.connectButton}
|
||||
</ActionButton>
|
||||
{connected && (<ActionButton variant='search' onClick={onSearch}>Search</ActionButton>)}
|
||||
{connected && (<ActionButton variant='search' onClick={onSearch}>{uiText.connections.serviceCard.searchButton}</ActionButton>)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ import '../ui/Modal.scss'
|
||||
import { type PagedSearchResponse, type ServiceItem, type SearchRequest, type SyncRequest } from '../../types/search'
|
||||
import { syncVectorData, search } from '../../api/searches'
|
||||
import type { ServiceType } from '../../types/connection'
|
||||
import { uiText } from '../../text/uiText'
|
||||
|
||||
interface Props {
|
||||
serviceType: ServiceType
|
||||
@@ -48,7 +49,7 @@ export function SearchModal({ serviceType, label, appUrl, username, onClose }: R
|
||||
const res = await search(req)
|
||||
setResults(res)
|
||||
} catch (err) {
|
||||
setSearchError(err instanceof Error ? err.message : 'Search failed')
|
||||
setSearchError(err instanceof Error ? err.message : uiText.search.searchFailed)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -61,7 +62,7 @@ export function SearchModal({ serviceType, label, appUrl, username, onClose }: R
|
||||
const req: SyncRequest = { appUrl, serviceType, username}
|
||||
await syncVectorData(req)
|
||||
} catch (err) {
|
||||
setSyncError(err instanceof Error ? err.message: 'Refreshing data failed')
|
||||
setSyncError(err instanceof Error ? err.message: uiText.search.syncFailed)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -70,8 +71,8 @@ export function SearchModal({ serviceType, label, appUrl, username, onClose }: R
|
||||
return (
|
||||
<dialog className='modal' ref={dialogRef}>
|
||||
<div className='modal__header'>
|
||||
<h2 className='modal__title' id='modal-title'>Search in {label}</h2>
|
||||
<button className='modal__close' onClick={onClose} aria-label='Close'>×</button>
|
||||
<h2 className='modal__title' id='modal-title'>{uiText.search.title(label)}</h2>
|
||||
<button className='modal__close' onClick={onClose} aria-label={uiText.modal.closeAriaLabel}>{uiText.modal.closeSymbol}</button>
|
||||
</div>
|
||||
<form className='modal__form' onSubmit={handleSubmit}>
|
||||
<div className='modal__field'>
|
||||
@@ -81,8 +82,8 @@ export function SearchModal({ serviceType, label, appUrl, username, onClose }: R
|
||||
{searchError && <p className='modal__error'>{searchError}</p>}
|
||||
{syncError && <p className='modal__error'>{syncError}</p>}
|
||||
<div className='modal__actions'>
|
||||
<button className='modal__other' title={`Syncs your ${serviceType} database for vectorization`} type='button' disabled={loading} onClick={handleSync}>Refresh Data</button>
|
||||
<button className='modal__submit' type='submit' disabled={loading}>Search</button>
|
||||
<button className='modal__other' title={uiText.search.syncTooltip(label)} type='button' disabled={loading} onClick={handleSync}>{uiText.search.refreshDataButton}</button>
|
||||
<button className='modal__submit' type='submit' disabled={loading}>{uiText.search.searchButton}</button>
|
||||
</div>
|
||||
</form>
|
||||
{results && (
|
||||
|
||||
Reference in New Issue
Block a user