This seems like a good pause point. The new Jitsi reports page is functional. The meetings log various activities and events.

This commit is contained in:
Scott Idem
2025-12-16 15:07:27 -05:00
parent ae49fa7b39
commit a9d1e30fc4
4 changed files with 249 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
<script lang="ts">
import { ae_util } from '$lib/ae_utils/ae_utils';
interface Props {
data: any;
}
let { data }: Props = $props();
let open_accordions = $state<{ [key: string]: boolean }>({});
function toggle_accordion(meeting_id: string) {
open_accordions[meeting_id] = !open_accordions[meeting_id];
}
</script>
<svelte:head>
<title>&AElig;: Jitsi Meeting Reports</title>
</svelte:head>
<div class="p-4 space-y-4">
<h1 class="h1">Jitsi Meeting Reports</h1>
{#if data.meetings && data.meetings.length > 0}
<div class="space-y-2">
{#each data.meetings as meeting (meeting.meeting_id)}
<div class="card card-hover">
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<header class="card-header p-2 cursor-pointer" onclick={() => toggle_accordion(meeting.meeting_id)}>
<div class="flex justify-between items-center w-full">
<div class="flex-1">
<!-- NOTE: Normally I would the "h3" class, but Novi classes make things look odd. -->
<h3 class="text-base">{meeting.room_name}</h3>
<p class="text-sm text-gray-500">{new Date(meeting.start_time).toLocaleString()}</p>
</div>
<div class="flex-none flex items-center space-x-4 text-sm mr-4">
<span>Duration: {meeting.final_duration}</span>
<span>Participants: {meeting.final_participant_count}</span>
</div>
<div class="flex-none">
<span class="transition-transform duration-200" class:rotate-180={open_accordions[meeting.meeting_id]}>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
</span>
</div>
</div>
</header>
{#if open_accordions[meeting.meeting_id]}
<div class="p-4 border-t border-gray-200 dark:border-gray-700 grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<!-- NOTE: Normally I would the "h4" class, but Novi classes make things look odd. -->
<h4 class="text-base">Event Timeline</h4>
{#if meeting.events && meeting.events.length > 0}
<ul class="list-disc list-inside space-y-2 mt-2">
{#each meeting.events as event}
<li>
<span class="font-mono text-xs">[{new Date(event.timestamp).toLocaleTimeString()}]</span>
<span class="font-semibold">{ae_util.to_title_case(event.action.replace('jitsi_meeting_', ''))}</span>
{#if event.details.full_name}
- by {event.details.full_name}
{/if}
</li>
{/each}
</ul>
{:else}
<p class="text-gray-500 italic mt-2">No discrete events recorded.</p>
{/if}
</div>
<div>
<!-- NOTE: Normally I would the "h4" class, but Novi classes make things look odd. -->
<h4 class="text-base">Final Participants</h4>
{#if meeting.final_participants && meeting.final_participants.length > 0}
<div class="table-container mt-2">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Role</th>
</tr>
</thead>
<tbody>
{#each meeting.final_participants as participant}
<tr>
<td>{participant.displayName}</td>
<td>{ae_util.to_title_case(participant.role)}</td>
</tr>
{/each}
</tbody>
</table>
</div>
{:else}
<p class="text-gray-500 italic mt-2">No participant data available.</p>
{/if}
</div>
</div>
{/if}
</div>
{/each}
</div>
{:else}
<div class="card p-4 text-center">
<h3 class="h3">No Meeting Reports Found</h3>
<p>There are no Jitsi activity logs to display.</p>
</div>
{/if}
</div>

View File

@@ -0,0 +1,28 @@
import type { PageLoad } from './$types';
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
import { load_jitsi_report } from '$lib/ae_reports/reports_functions';
import { get } from 'svelte/store';
export const load: PageLoad = async ({ fetch }) => {
console.log('*** /idaa/jitsi_reports/+page.ts ***');
const api_cfg = get(ae_api);
const account_id = get(ae_loc)?.account_id;
if (!api_cfg || !account_id) {
console.error('API config or Account ID not available for loading Jitsi reports.');
return {
meetings: []
};
}
const meetings = await load_jitsi_report({
api_cfg,
account_id,
log_lvl: 1
});
return {
meetings
};
};