Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions resources/js/hooks/use-socket-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,22 @@ export function useRealtimeRecord<T extends { id: number }>(initial: T | null |
/**
* Manages paginated Inertia data with realtime socket updates.
*
* Listens for socket events matching `{eventPrefix}.updated` (replace row),
* and `{eventPrefix}.deleted` (remove row) automatically.
* Listens for socket events matching `{eventPrefix}.created` (prepend row),
* `{eventPrefix}.updated` (replace row), and `{eventPrefix}.deleted` (remove row) automatically.
*
* Socket events are broadcast project-wide, so pass a `scope` of field/value pairs
* (e.g. `{ server_id: server.id }`) that created records must match before trigger refreshes
*
* Returns the live data and setter for custom handling.
*/
export function useRealtime<T extends { id: number }>(
initialData: PaginatedData<T>,
eventPrefix: string,
scope?: Partial<T>,
): [PaginatedData<T>, Dispatch<SetStateAction<PaginatedData<T>>>] {
const [data, setData] = useState<PaginatedData<T>>(initialData);
const scopeRef = useRef(scope);
scopeRef.current = scope;

useEffect(() => {
setData(initialData);
Expand All @@ -122,6 +128,9 @@ export function useRealtime<T extends { id: number }>(

switch (action) {
case 'created':
if (!Object.entries(scopeRef.current ?? {}).every(([key, value]) => (eventData as Record<string, unknown>)[key] === value)) {
break;
}
setData((prev) => ({
...prev,
data: [eventData as unknown as T, ...prev.data],
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/backups/files.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Page = {

export default function Files() {
const page = usePage<Page>();
const [files] = useRealtime<BackupFile>(page.props.files, 'backup-file');
const [files] = useRealtime<BackupFile>(page.props.files, 'backup-file', { backup_id: page.props.backup.id });

const runBackupForm = useForm();
const runBackup = () => {
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/backups/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Page = {

export default function Backups() {
const page = usePage<Page>();
const [backups] = useRealtime<Backup>(page.props.backups, 'backup');
const [backups] = useRealtime<Backup>(page.props.backups, 'backup', { server_id: page.props.server.id });

return (
<ServerLayout>
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/commands/show.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type Page = {

export default function Show() {
const page = usePage<Page>();
const [executions] = useRealtime<CommandExecution>(page.props.executions, 'command-execution');
const [executions] = useRealtime<CommandExecution>(page.props.executions, 'command-execution', { command_id: page.props.command.id });

const breadcrumbs: BreadcrumbItem[] = [
{
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/php/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function PHP() {
installedVersions: PaginatedData<Service>;
}>();

const [installedVersions] = useRealtime<Service>(page.props.installedVersions, 'service');
const [installedVersions] = useRealtime<Service>(page.props.installedVersions, 'service', { server_id: page.props.server.id, type: 'php' });

return (
<ServerLayout>
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/redirects/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default function Redirects() {
redirects: PaginatedData<Redirect>;
}>();

const [redirects] = useRealtime<Redirect>(page.props.redirects, 'redirect');
const [redirects] = useRealtime<Redirect>(page.props.redirects, 'redirect', { site_id: page.props.site.id });

return (
<ServerLayout>
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/scripts/show.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type Page = {

export default function Show() {
const page = usePage<Page>();
const [executions] = useRealtime<ScriptExecution>(page.props.executions, 'script-execution');
const [executions] = useRealtime<ScriptExecution>(page.props.executions, 'script-execution', { script_id: page.props.script.id });

const breadcrumbs: BreadcrumbItem[] = [
{
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/server-logs/components/logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function Logs({ server, site }: { server: Server; site?: Site })
const [currentPage, setCurrentPage] = useState(1);

const query = useQuery({
queryKey: ['serverLogs', currentPage],
queryKey: ['serverLogs', server.id, site?.id, currentPage],
queryFn: async () => {
return (
await axios.get(route('logs.json', { server: server.id, site: site?.id }), {
Expand Down
7 changes: 5 additions & 2 deletions resources/js/pages/server-logs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ export default function ServerLogs() {
title: string;
server: Server;
logs: PaginatedData<ServerLog>;
remote: boolean;
remote?: boolean;
}>();

const [logs] = useRealtime<ServerLog>(page.props.logs, 'server-log');
const [logs] = useRealtime<ServerLog>(page.props.logs, 'server-log', {
server_id: page.props.server.id,
is_remote: !!page.props.remote,
});

return (
<ServerLayout>
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/server-ssls/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function ServerSsls() {
domains: Domain[];
}>();

const [ssls] = useRealtime<SSL>(page.props.ssls, 'ssl');
const [ssls] = useRealtime<SSL>(page.props.ssls, 'ssl', { server_id: page.props.server.id, site_id: null });

return (
<ServerLayout>
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/servers/installing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function InstallingServer() {
logs: PaginatedData<ServerLog>;
}>();

const [logs] = useRealtime<ServerLog>(page.props.logs, 'server-log');
const [logs] = useRealtime<ServerLog>(page.props.logs, 'server-log', { server_id: page.props.server.id });

return (
<Container className="max-w-5xl">
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/services/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function WorkerIndex() {
services: PaginatedData<Service>;
}>();

const [services] = useRealtime<Service>(page.props.services, 'service');
const [services] = useRealtime<Service>(page.props.services, 'service', { server_id: page.props.server.id });

return (
<ServerLayout>
Expand Down
4 changes: 3 additions & 1 deletion resources/js/pages/sites/logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { PaginatedData } from '@/types';
import { ServerLog } from '@/types/server-log';
import { DataTable } from '@/components/data-table';
import { columns } from '@/pages/server-logs/components/columns';
import { useRealtime } from '@/hooks/use-socket-events';

type Page = {
server: Server;
Expand All @@ -19,6 +20,7 @@ type Page = {

export default function ShowSite() {
const page = usePage<Page>();
const [logs] = useRealtime<ServerLog>(page.props.logs, 'server-log', { site_id: page.props.site.id });

return (
<ServerLayout>
Expand All @@ -31,7 +33,7 @@ export default function ShowSite() {

<SiteBanners site={page.props.site} />

<DataTable columns={columns} paginatedData={page.props.logs} searchable />
<DataTable columns={columns} paginatedData={logs} searchable />
</Container>
</ServerLayout>
);
Expand Down
6 changes: 5 additions & 1 deletion resources/js/pages/workers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ export default function WorkerIndex() {
}>();
const dialog = useDialog();

const [workers] = useRealtime<Worker>(page.props.workers, 'worker');
const [workers] = useRealtime<Worker>(
page.props.workers,
'worker',
page.props.site ? { site_id: page.props.site.id } : { server_id: page.props.server.id },
);

return (
<ServerLayout>
Expand Down
2 changes: 1 addition & 1 deletion resources/js/types/server-log.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export interface ServerLog {
id: number;
server_id: number;
site_id?: number;
site_id: number | null;
type: string;
name: string;
disk: string;
Expand Down
Loading