Skip to content

Commit

Permalink
Merge pull request #260 from binbat/feat/web-auto-update-ui
Browse files Browse the repository at this point in the history
feat(web): update ui after login or stream operation
  • Loading branch information
a-wing authored Dec 14, 2024
2 parents a789107 + 3c17e3e commit 1bb1f42
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 26 deletions.
2 changes: 1 addition & 1 deletion web/liveion/components/login.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from 'preact/hooks';
import { TargetedEvent } from 'preact/compat';
import { Alert, Button, Modal } from 'react-daisyui';
import { Alert, Button, Loading, Modal } from 'react-daisyui';
import { WretchError } from 'wretch/resolver';

import * as api from '@/shared/api';
Expand Down
15 changes: 13 additions & 2 deletions web/liveman/components/nodes-table.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Button, Checkbox, Dropdown, Link, Table } from 'react-daisyui';
import { useContext, useEffect } from 'preact/hooks';

import { Badge, Button, Checkbox, Dropdown, Link, Table } from 'react-daisyui';
import { ArrowPathIcon, EllipsisHorizontalIcon } from '@heroicons/react/24/outline';

import { TokenContext } from '@/shared/context';
import { useRefreshTimer } from '@/shared/hooks/use-refresh-timer';

import { type Node, getNodes } from '../api';
Expand All @@ -12,11 +15,19 @@ async function getNodesSorted() {

export function NodesTable() {
const nodes = useRefreshTimer([], getNodesSorted);
const tokenContext = useContext(TokenContext);

useEffect(() => {
if (tokenContext.token.length > 0) {
nodes.updateData();
}
}, [tokenContext.token]);

return (
<>
<div className="flex items-center gap-2 px-4 h-12">
<span className="font-bold text-lg mr-auto">Nodes (total: {nodes.data.length})</span>
<span className="font-bold text-lg">Nodes</span>
<Badge color="ghost" className="font-bold mr-auto">{nodes.data.length}</Badge>
<Button
size="sm"
color="ghost"
Expand Down
2 changes: 1 addition & 1 deletion web/liveman/liveman.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback, useRef, useState } from 'preact/hooks';
import { Button } from 'react-daisyui';

import type { Stream } from '@/shared/api';
import { type Stream } from '@/shared/api';
import { useNeedAuthorization } from '@/shared/hooks/use-need-authorization';
import { StreamsTable } from '@/shared/components/streams-table';
import { PageLayout } from '@/shared/components/page-layout';
Expand Down
8 changes: 4 additions & 4 deletions web/shared/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ export const addUnauthorizedCallback = authMiddleware.addUnauthorizedCallback;
export const removeUnauthorizedCallback = authMiddleware.removeUnauthorizedCallback;

export function deleteSession(streamId: string, clientId: string) {
return w.url(`/session/${streamId}/${clientId}`).delete();
return w.url(`/session/${streamId}/${clientId}`).delete().res();
}

export function createStream(streamId: string) {
return w.url(`/api/streams/${streamId}`).post();
return w.url(`/api/streams/${streamId}`).post().res();
}

export function deleteStream(streamId: string) {
return w.url(`/api/streams/${streamId}`).delete();
return w.url(`/api/streams/${streamId}`).delete().res();
}

type SessionConnectionState =
Expand Down Expand Up @@ -66,5 +66,5 @@ export function getStreams() {
}

export function cascade(streamId: string, params: Cascade) {
return w.url(`/api/cascade/${streamId}`).post(params);
return w.url(`/api/cascade/${streamId}`).post(params).res();
}
2 changes: 1 addition & 1 deletion web/shared/authorization-middleware.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ConfiguredMiddleware } from 'wretch';
import { type ConfiguredMiddleware } from 'wretch';

const Authorization = 'Authorization';

Expand Down
8 changes: 7 additions & 1 deletion web/shared/components/dialog-clients.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { formatTime } from '../utils';
interface Props {
id: string
sessions: Session[]
onClientKicked: () => void
}

export interface IClientsDialog {
Expand All @@ -25,6 +26,11 @@ export const ClientsDialog = forwardRef<IClientsDialog, Props>((props: Props, re
};
});

const handleKickClient = async (streamId: string, clientId: string) => {
await deleteSession(streamId, clientId);
props.onClientKicked();
};

return (
<Modal ref={refDialog} className="min-w-md max-w-[unset] w-[unset]">
<Modal.Header className="mb-2">
Expand All @@ -44,7 +50,7 @@ export const ClientsDialog = forwardRef<IClientsDialog, Props>((props: Props, re
<span>{c.id + (c.reforward ? '(reforward)' : '')}</span>
<span>{c.state}</span>
<span>{formatTime(c.createdAt)}</span>
<Button size="sm" color="error" onClick={() => deleteSession(props.id, c.id)}>Kick</Button>
<Button size="sm" color="error" onClick={() => handleKickClient(props.id, c.id)}>Kick</Button>
</Table.Row>
): <tr><td colspan={4} className="text-center">N/A</td></tr>}
</Table.Body>
Expand Down
6 changes: 4 additions & 2 deletions web/shared/components/dialog-new-stream.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createStream } from '../api';

interface Props {
onNewStreamId(id: string): void
onStreamCreated(): void
}

export interface INewStreamDialog {
Expand All @@ -29,9 +30,10 @@ export const NewStreamDialog = forwardRef<INewStreamDialog, Props>((props, ref)
setStreamId(e.currentTarget.value);
};

const onConfirmNewStreamId = (_e: Event) => {
const onConfirmNewStreamId = async (_e: Event) => {
props.onNewStreamId(streamId);
createStream(streamId);
await createStream(streamId);
props.onStreamCreated();
};

return (
Expand Down
6 changes: 3 additions & 3 deletions web/shared/components/page-layout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { PropsWithChildren } from 'preact/compat';
import { type PropsWithChildren } from 'preact/compat';
import { PageHeader } from './page-header';

import { ITokenContext, TokenContext } from '../context';
import { type ITokenContext, TokenContext } from '../context';

export type PageLayoutProps = ITokenContext & PropsWithChildren;
export type PageLayoutProps = PropsWithChildren<ITokenContext>;

export function PageLayout({ token, children }: PageLayoutProps) {
return (
Expand Down
35 changes: 24 additions & 11 deletions web/shared/components/streams-table.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { useState, useRef, useEffect, useContext } from 'preact/hooks';
import { ReactNode } from 'preact/compat';
import { type ReactNode } from 'preact/compat';

import { Button, Checkbox, Table } from 'react-daisyui';
import { Badge, Button, Checkbox, Table } from 'react-daisyui';
import { ArrowPathIcon, ArrowRightEndOnRectangleIcon, PlusIcon } from '@heroicons/react/24/outline';

import { type Stream, getStreams, deleteStream } from '../api';
import { formatTime, nextSeqId } from '../utils';
import { useRefreshTimer } from '../hooks/use-refresh-timer';
import { TokenContext } from '../context';

import { IClientsDialog, ClientsDialog } from './dialog-clients';
import { ICascadeDialog, CascadePullDialog, CascadePushDialog } from './dialog-cascade';
import { IPreviewDialog, PreviewDialog } from './dialog-preview';
import { IWebStreamDialog, WebStreamDialog } from './dialog-web-stream';
import { INewStreamDialog, NewStreamDialog } from './dialog-new-stream';
import { type IClientsDialog, ClientsDialog } from './dialog-clients';
import { type ICascadeDialog, CascadePullDialog, CascadePushDialog } from './dialog-cascade';
import { type IPreviewDialog, PreviewDialog } from './dialog-preview';
import { type IWebStreamDialog, WebStreamDialog } from './dialog-web-stream';
import { type INewStreamDialog, NewStreamDialog } from './dialog-new-stream';

async function getStreamsSorted() {
const streams = await getStreams();
Expand All @@ -40,6 +40,12 @@ export function StreamsTable(props: StreamTableProps) {
const refPreviewStreams = useRef<Map<string, IPreviewDialog>>(new Map());
const tokenContext = useContext(TokenContext);

useEffect(() => {
if (tokenContext.token.length > 0) {
streams.updateData();
}
}, [tokenContext.token]);

const handleViewClients = (id: string) => {
setSelectedStreamId(id);
refClients.current?.show();
Expand Down Expand Up @@ -114,10 +120,16 @@ export function StreamsTable(props: StreamTableProps) {
window.open(url);
};

const handleDestroyStream = async (id: string) => {
await deleteStream(id);
await streams.updateData();
};

return (
<>
<div className="flex items-center gap-2 px-4 h-12">
<span className="font-bold text-lg mr-auto">Streams (total: {streams.data.length})</span>
<span className="font-bold text-lg">Streams</span>
<Badge color="ghost" className="font-bold mr-auto">{streams.data.length}</Badge>
{props.showCascade ? (
<Button
size="sm"
Expand Down Expand Up @@ -172,7 +184,7 @@ export function StreamsTable(props: StreamTableProps) {
<Button size="sm" onClick={() => handleOpenPlayerPage(i.id)}>Player</Button>
<Button size="sm" onClick={() => handleOpenDebuggerPage(i.id)}>Debugger</Button>
{props.renderExtraActions?.(i)}
<Button size="sm" color="error" onClick={() => deleteStream(i.id)}>Destroy</Button>
<Button size="sm" color="error" onClick={() => handleDestroyStream(i.id)}>Destroy</Button>
</div>
</Table.Row>
) : <tr><td colspan={6} className="text-center">N/A</td></tr>}
Expand All @@ -187,14 +199,15 @@ export function StreamsTable(props: StreamTableProps) {
onClick={handleNewStream}
>New Stream</Button>
{webStreams.map(s =>
<Button size="sm" onClick={() => { handleOpenWebStream(s); }}>{s}</Button>
<Button size="sm" onClick={() => handleOpenWebStream(s)}>{s}</Button>
)}
</div>

<ClientsDialog
ref={refClients}
id={selectedStreamId}
sessions={streams.data.find(s => s.id == selectedStreamId)?.subscribe.sessions ?? []}
onClientKicked={streams.updateData}
/>

{props.showCascade ? (
Expand All @@ -218,7 +231,7 @@ export function StreamsTable(props: StreamTableProps) {
/>
)}

<NewStreamDialog ref={refNewStream} onNewStreamId={handleNewStreamId} />
<NewStreamDialog ref={refNewStream} onNewStreamId={handleNewStreamId} onStreamCreated={streams.updateData} />

{webStreams.map(s =>
<WebStreamDialog
Expand Down

0 comments on commit 1bb1f42

Please sign in to comment.