diff --git a/README.md b/README.md index f3dfae0f..b1b68317 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ A self-hosted, real-time collaborative travel planner — with maps, budgets, pa
-Demo +Demo   Docker   diff --git a/client/src/api/client.ts b/client/src/api/client.ts index 837ed16b..57c90fbb 100644 --- a/client/src/api/client.ts +++ b/client/src/api/client.ts @@ -209,7 +209,7 @@ export const oauthApi = { clients: { list: () => apiClient.get('/oauth/clients').then(r => r.data), - create: (data: { name: string; redirect_uris: string[]; allowed_scopes: string[] }) => + create: (data: { name: string; redirect_uris?: string[]; allowed_scopes: string[]; allows_client_credentials?: boolean }) => apiClient.post('/oauth/clients', data).then(r => r.data), rotate: (id: string) => apiClient.post(`/oauth/clients/${id}/rotate`).then(r => r.data), delete: (id: string) => apiClient.delete(`/oauth/clients/${id}`).then(r => r.data), @@ -407,8 +407,20 @@ export const journeyApi = { reorderEntries: (journeyId: number, orderedIds: number[]) => apiClient.put(`/journeys/${journeyId}/entries/reorder`, { orderedIds }).then(r => r.data), // Photos - uploadPhotos: (entryId: number, formData: FormData) => apiClient.post(`/journeys/entries/${entryId}/photos`, formData, { headers: { 'Content-Type': undefined as any } }).then(r => r.data), - uploadGalleryPhotos: (journeyId: number, formData: FormData) => apiClient.post(`/journeys/${journeyId}/gallery/photos`, formData, { headers: { 'Content-Type': undefined as any } }).then(r => r.data), + uploadPhotos: (entryId: number, formData: FormData, opts?: { onUploadProgress?: (e: import('axios').AxiosProgressEvent) => void; idempotencyKey?: string; signal?: AbortSignal }) => + apiClient.post(`/journeys/entries/${entryId}/photos`, formData, { + headers: { 'Content-Type': undefined as any, ...(opts?.idempotencyKey ? { 'X-Idempotency-Key': opts.idempotencyKey } : {}) }, + timeout: 0, + onUploadProgress: opts?.onUploadProgress, + signal: opts?.signal, + }).then(r => r.data), + uploadGalleryPhotos: (journeyId: number, formData: FormData, opts?: { onUploadProgress?: (e: import('axios').AxiosProgressEvent) => void; idempotencyKey?: string; signal?: AbortSignal }) => + apiClient.post(`/journeys/${journeyId}/gallery/photos`, formData, { + headers: { 'Content-Type': undefined as any, ...(opts?.idempotencyKey ? { 'X-Idempotency-Key': opts.idempotencyKey } : {}) }, + timeout: 0, + onUploadProgress: opts?.onUploadProgress, + signal: opts?.signal, + }).then(r => r.data), addProviderPhotosToGallery: (journeyId: number, provider: string, assetIds: string[], passphrase?: string) => apiClient.post(`/journeys/${journeyId}/gallery/provider-photos`, { provider, asset_ids: assetIds, ...(passphrase ? { passphrase } : {}) }).then(r => r.data), addProviderPhoto: (entryId: number, provider: string, assetId: string, caption?: string, passphrase?: string) => apiClient.post(`/journeys/entries/${entryId}/provider-photos`, { provider, asset_id: assetId, caption, ...(passphrase ? { passphrase } : {}) }).then(r => r.data), addProviderPhotos: (entryId: number, provider: string, assetIds: string[], caption?: string, passphrase?: string) => apiClient.post(`/journeys/entries/${entryId}/provider-photos`, { provider, asset_ids: assetIds, caption, ...(passphrase ? { passphrase } : {}) }).then(r => r.data), diff --git a/client/src/components/Journey/MobileEntryView.tsx b/client/src/components/Journey/MobileEntryView.tsx index 766f8b7f..fc340f4a 100644 --- a/client/src/components/Journey/MobileEntryView.tsx +++ b/client/src/components/Journey/MobileEntryView.tsx @@ -52,7 +52,7 @@ export default function MobileEntryView({ entry, readOnly, publicPhotoUrl, onClo const dateStr = date.toLocaleDateString(undefined, { weekday: 'long', day: 'numeric', month: 'long' }) return ( -
+
{/* Top bar */}
@@ -360,7 +369,15 @@ export default function IntegrationsTab(): React.ReactElement {
-

{client.name}

+
+

{client.name}

+ {client.allows_client_credentials && ( + + {t('settings.oauth.badge.machine')} + + )} +

{t('settings.oauth.clientId')}: {client.client_id} {t('settings.mcp.tokenCreatedAt')} {new Date(client.created_at).toLocaleDateString(locale)} @@ -616,15 +633,26 @@ export default function IntegrationsTab(): React.ReactElement { autoFocus />

-
- -