From e2f30ee28a86ff635eeb6246e4586de0de99dbba Mon Sep 17 00:00:00 2001 From: senke Date: Fri, 6 Feb 2026 02:02:00 +0100 Subject: [PATCH] refactor(studio): ConnectivityView module, re-export, stories - Module connectivity-view: types, useConnectivityView, WebDAV, Webhooks, Skeleton, orchestrator ConnectivityView - Re-export from ConnectivityView.tsx - Stories: Default, Loading (Skeleton); decorator min-h-layout-page - Fix: text-[10px] -> text-xs (Mount Password hint) Co-authored-by: Cursor --- .../studio/ConnectivityView.stories.tsx | 24 +++ .../components/studio/ConnectivityView.tsx | 193 +----------------- .../connectivity-view/ConnectivityView.tsx | 34 +++ .../ConnectivityViewSkeleton.tsx | 47 +++++ .../ConnectivityViewWebDAV.tsx | 91 +++++++++ .../ConnectivityViewWebhooks.tsx | 83 ++++++++ .../studio/connectivity-view/index.ts | 7 + .../studio/connectivity-view/types.ts | 8 + .../connectivity-view/useConnectivityView.ts | 58 ++++++ 9 files changed, 353 insertions(+), 192 deletions(-) create mode 100644 apps/web/src/components/studio/ConnectivityView.stories.tsx create mode 100644 apps/web/src/components/studio/connectivity-view/ConnectivityView.tsx create mode 100644 apps/web/src/components/studio/connectivity-view/ConnectivityViewSkeleton.tsx create mode 100644 apps/web/src/components/studio/connectivity-view/ConnectivityViewWebDAV.tsx create mode 100644 apps/web/src/components/studio/connectivity-view/ConnectivityViewWebhooks.tsx create mode 100644 apps/web/src/components/studio/connectivity-view/index.ts create mode 100644 apps/web/src/components/studio/connectivity-view/types.ts create mode 100644 apps/web/src/components/studio/connectivity-view/useConnectivityView.ts diff --git a/apps/web/src/components/studio/ConnectivityView.stories.tsx b/apps/web/src/components/studio/ConnectivityView.stories.tsx new file mode 100644 index 000000000..4e8647b4d --- /dev/null +++ b/apps/web/src/components/studio/ConnectivityView.stories.tsx @@ -0,0 +1,24 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { ConnectivityView, ConnectivityViewSkeleton } from './connectivity-view'; + +const meta: Meta = { + title: 'Components/Features/Studio/ConnectivityView', + component: ConnectivityView, + tags: ['autodocs'], + decorators: [ + (Story) => ( +
+ +
+ ), + ], +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const Loading: Story = { + render: () => , +}; diff --git a/apps/web/src/components/studio/ConnectivityView.tsx b/apps/web/src/components/studio/ConnectivityView.tsx index 32644831e..76bda5316 100644 --- a/apps/web/src/components/studio/ConnectivityView.tsx +++ b/apps/web/src/components/studio/ConnectivityView.tsx @@ -1,192 +1 @@ -import React, { useState } from 'react'; -import { Card } from '../ui/card'; -import { Button } from '../ui/button'; -import { Input } from '../ui/input'; -import { Globe, Copy, Plus, Trash2, CheckCircle, Folder } from 'lucide-react'; -import { useToast } from '../../components/feedback/ToastProvider'; - -export const ConnectivityView: React.FC = () => { - const { addToast } = useToast(); - - // WebDAV State - const [webdavPass, setWebdavPass] = useState('****'); - - // Webhooks State - const [webhooks, setWebhooks] = useState([ - { - id: '1', - url: 'https://api.myapp.com/hooks/veza', - events: ['file.upload', 'file.delete'], - }, - ]); - const [newHookUrl, setNewHookUrl] = useState(''); - - const generateWebdavPass = () => { - setWebdavPass(`wd-${Math.random().toString(36).substr(2, 10)}`); - addToast('New WebDAV password generated', 'success'); - }; - - const addWebhook = () => { - if (!newHookUrl) return; - setWebhooks([ - ...webhooks, - { id: Date.now().toString(), url: newHookUrl, events: ['file.upload'] }, - ]); - setNewHookUrl(''); - addToast('Webhook endpoint added', 'success'); - }; - - const copyToClipboard = (text: string) => { - navigator.clipboard.writeText(text); - addToast('Copied to clipboard'); - }; - - return ( -
- {/* WebDAV Mount Section */} - -
-
-

- Directory Mount - (WebDAV) -

-

- Access your Cloud Studio files directly from your OS file explorer - or DAW. -

-
-
- PROTOCOL ACTIVE -
-
- -
-
- -
-
- https://webdav.veza.io/u/cyber_producer -
- -
-
-
- -
-
- cyber_producer -
- -
-
-
- -
-
- {webdavPass} -
- -
-

- Use this specific password for mounting. Do not use your account - login password. -

-
-
-
- - {/* Webhooks Section */} - -
-
-

- Storage Webhooks -

-

- Trigger actions in external apps when files change. -

-
-
- -
-
- setNewHookUrl(e.target.value)} - /> - -
- -
- {webhooks.map((hook) => ( -
-
-
- {hook.url} -
-
- {hook.events.map((ev) => ( - - {ev} - - ))} -
-
-
-
- Active -
- -
-
- ))} -
-
-
-
- ); -}; +export { ConnectivityView, ConnectivityViewSkeleton } from './connectivity-view'; diff --git a/apps/web/src/components/studio/connectivity-view/ConnectivityView.tsx b/apps/web/src/components/studio/connectivity-view/ConnectivityView.tsx new file mode 100644 index 000000000..89ef210c5 --- /dev/null +++ b/apps/web/src/components/studio/connectivity-view/ConnectivityView.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { useConnectivityView } from './useConnectivityView'; +import { ConnectivityViewWebDAV } from './ConnectivityViewWebDAV'; +import { ConnectivityViewWebhooks } from './ConnectivityViewWebhooks'; + +export function ConnectivityView() { + const { + webdavPass, + webhooks, + newHookUrl, + setNewHookUrl, + generateWebdavPass, + addWebhook, + removeWebhook, + copyToClipboard, + } = useConnectivityView(); + + return ( +
+ + +
+ ); +} diff --git a/apps/web/src/components/studio/connectivity-view/ConnectivityViewSkeleton.tsx b/apps/web/src/components/studio/connectivity-view/ConnectivityViewSkeleton.tsx new file mode 100644 index 000000000..48123f7c3 --- /dev/null +++ b/apps/web/src/components/studio/connectivity-view/ConnectivityViewSkeleton.tsx @@ -0,0 +1,47 @@ +/** + * Skeleton for ConnectivityView — layout primitives, no arbitrary values. + */ +export function ConnectivityViewSkeleton() { + return ( +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ); +} diff --git a/apps/web/src/components/studio/connectivity-view/ConnectivityViewWebDAV.tsx b/apps/web/src/components/studio/connectivity-view/ConnectivityViewWebDAV.tsx new file mode 100644 index 000000000..b95197783 --- /dev/null +++ b/apps/web/src/components/studio/connectivity-view/ConnectivityViewWebDAV.tsx @@ -0,0 +1,91 @@ +import { Card } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Folder, Copy } from 'lucide-react'; +import { DEFAULT_WEBDAV_URL, DEFAULT_WEBDAV_USER } from './types'; + +interface ConnectivityViewWebDAVProps { + webdavPass: string; + onGeneratePass: () => void; + onCopy: (text: string) => void; +} + +export function ConnectivityViewWebDAV({ + webdavPass, + onGeneratePass, + onCopy, +}: ConnectivityViewWebDAVProps) { + return ( + +
+
+

+ Directory Mount (WebDAV) +

+

+ Access your Cloud Studio files directly from your OS file explorer or DAW. +

+
+
+ PROTOCOL ACTIVE +
+
+ +
+
+ +
+
+ {DEFAULT_WEBDAV_URL} +
+ +
+
+
+ +
+
+ {DEFAULT_WEBDAV_USER} +
+ +
+
+
+ +
+
+ {webdavPass} +
+ +
+

+ Use this specific password for mounting. Do not use your account login password. +

+
+
+
+ ); +} diff --git a/apps/web/src/components/studio/connectivity-view/ConnectivityViewWebhooks.tsx b/apps/web/src/components/studio/connectivity-view/ConnectivityViewWebhooks.tsx new file mode 100644 index 000000000..de3fa13f7 --- /dev/null +++ b/apps/web/src/components/studio/connectivity-view/ConnectivityViewWebhooks.tsx @@ -0,0 +1,83 @@ +import { Card } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Globe, Plus, Trash2, CheckCircle } from 'lucide-react'; +import type { WebhookItem } from './types'; + +interface ConnectivityViewWebhooksProps { + webhooks: WebhookItem[]; + newHookUrl: string; + onNewHookUrlChange: (value: string) => void; + onAddWebhook: () => void; + onRemoveWebhook: (id: string) => void; +} + +export function ConnectivityViewWebhooks({ + webhooks, + newHookUrl, + onNewHookUrlChange, + onAddWebhook, + onRemoveWebhook, +}: ConnectivityViewWebhooksProps) { + return ( + +
+
+

+ Storage Webhooks +

+

+ Trigger actions in external apps when files change. +

+
+
+ +
+
+ onNewHookUrlChange(e.target.value)} + /> + +
+ +
+ {webhooks.map((hook) => ( +
+
+
{hook.url}
+
+ {hook.events.map((ev) => ( + + {ev} + + ))} +
+
+
+
+ Active +
+ +
+
+ ))} +
+
+
+ ); +} diff --git a/apps/web/src/components/studio/connectivity-view/index.ts b/apps/web/src/components/studio/connectivity-view/index.ts new file mode 100644 index 000000000..565832629 --- /dev/null +++ b/apps/web/src/components/studio/connectivity-view/index.ts @@ -0,0 +1,7 @@ +export { ConnectivityView } from './ConnectivityView'; +export { ConnectivityViewSkeleton } from './ConnectivityViewSkeleton'; +export { ConnectivityViewWebDAV } from './ConnectivityViewWebDAV'; +export { ConnectivityViewWebhooks } from './ConnectivityViewWebhooks'; +export { useConnectivityView } from './useConnectivityView'; +export { DEFAULT_WEBDAV_URL, DEFAULT_WEBDAV_USER } from './types'; +export type { WebhookItem } from './types'; diff --git a/apps/web/src/components/studio/connectivity-view/types.ts b/apps/web/src/components/studio/connectivity-view/types.ts new file mode 100644 index 000000000..4b0695e19 --- /dev/null +++ b/apps/web/src/components/studio/connectivity-view/types.ts @@ -0,0 +1,8 @@ +export interface WebhookItem { + id: string; + url: string; + events: string[]; +} + +export const DEFAULT_WEBDAV_URL = 'https://webdav.veza.io/u/cyber_producer'; +export const DEFAULT_WEBDAV_USER = 'cyber_producer'; diff --git a/apps/web/src/components/studio/connectivity-view/useConnectivityView.ts b/apps/web/src/components/studio/connectivity-view/useConnectivityView.ts new file mode 100644 index 000000000..e5203048f --- /dev/null +++ b/apps/web/src/components/studio/connectivity-view/useConnectivityView.ts @@ -0,0 +1,58 @@ +import { useState, useCallback } from 'react'; +import { useToast } from '@/components/feedback/ToastProvider'; +import type { WebhookItem } from './types'; + +export function useConnectivityView() { + const { addToast } = useToast(); + const [webdavPass, setWebdavPass] = useState('****'); + const [webhooks, setWebhooks] = useState([ + { + id: '1', + url: 'https://api.myapp.com/hooks/veza', + events: ['file.upload', 'file.delete'], + }, + ]); + const [newHookUrl, setNewHookUrl] = useState(''); + + const generateWebdavPass = useCallback(() => { + setWebdavPass(`wd-${Math.random().toString(36).substring(2, 12)}`); + addToast('New WebDAV password generated', 'success'); + }, [addToast]); + + const addWebhook = useCallback(() => { + if (!newHookUrl.trim()) return; + setWebhooks((prev) => [ + ...prev, + { + id: Date.now().toString(), + url: newHookUrl.trim(), + events: ['file.upload'], + }, + ]); + setNewHookUrl(''); + addToast('Webhook endpoint added', 'success'); + }, [newHookUrl, addToast]); + + const removeWebhook = useCallback((id: string) => { + setWebhooks((prev) => prev.filter((h) => h.id !== id)); + }, []); + + const copyToClipboard = useCallback( + (text: string) => { + navigator.clipboard.writeText(text); + addToast('Copied to clipboard'); + }, + [addToast], + ); + + return { + webdavPass, + webhooks, + newHookUrl, + setNewHookUrl, + generateWebdavPass, + addWebhook, + removeWebhook, + copyToClipboard, + }; +}