Tighten Jitsi report exclusions
Use Jitsi url_params.uuid for exclusion where available, preserve url_params in cached activity logs, and add the temporary staff-name fallback behind the same edit-mode toggle. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { untrack } from 'svelte';
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import { load_jitsi_report } from '$lib/ae_reports/reports_functions';
|
||||
import {
|
||||
load_jitsi_report,
|
||||
load_jitsi_report_from_cache
|
||||
} from '$lib/ae_reports/reports_functions';
|
||||
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
|
||||
import { idaa_loc } from '$lib/stores/ae_idaa_stores';
|
||||
import JitsiUrlBuilder from './ae_idaa_comp__jitsi_url_builder.svelte';
|
||||
@@ -92,20 +95,42 @@ $effect(() => {
|
||||
meetings_error = null;
|
||||
|
||||
untrack(() => {
|
||||
void load_jitsi_report({
|
||||
api_cfg,
|
||||
account_id,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then((m: MeetingReport[]) => {
|
||||
meetings_all = m ?? [];
|
||||
meetings_loading = false;
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
meetings_error =
|
||||
err instanceof Error ? err.message : String(err);
|
||||
meetings_loading = false;
|
||||
void (async () => {
|
||||
const cached = await load_jitsi_report_from_cache({
|
||||
account_id,
|
||||
log_lvl: 1
|
||||
});
|
||||
|
||||
if (cached && cached.length > 0) {
|
||||
meetings_all = cached;
|
||||
meetings_loading = false;
|
||||
void load_jitsi_report({
|
||||
api_cfg,
|
||||
account_id,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then((m: MeetingReport[]) => {
|
||||
meetings_all = m ?? [];
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
console.warn('Jitsi report background refresh failed.', err);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const fresh = await load_jitsi_report({
|
||||
api_cfg,
|
||||
account_id,
|
||||
log_lvl: 1
|
||||
});
|
||||
meetings_all = fresh ?? [];
|
||||
} catch (err: unknown) {
|
||||
meetings_error = err instanceof Error ? err.message : String(err);
|
||||
} finally {
|
||||
meetings_loading = false;
|
||||
}
|
||||
})();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -118,6 +143,7 @@ let exclude_uuids = $derived<string[]>(
|
||||
?.jitsi_exclude_uuids
|
||||
).map((uuid) => uuid.toLowerCase())
|
||||
);
|
||||
const temp_excluded_names = ['Scott I.', 'Brie P.', 'Michelle V.'];
|
||||
let exclude_names = $derived<string[]>(
|
||||
normalize_list(
|
||||
($ae_loc.site_cfg_json as Record<string, unknown>)
|
||||
@@ -132,7 +158,12 @@ let known_meetings = $derived<string[]>(
|
||||
);
|
||||
let exclude_uuid_set = $derived(new Set(exclude_uuids));
|
||||
let exclude_name_set = $derived(new Set(exclude_names));
|
||||
let temp_excluded_name_set = $derived(
|
||||
new Set(temp_excluded_names.map((name) => name.toLowerCase()))
|
||||
);
|
||||
let known_meeting_set = $derived(new Set(known_meetings));
|
||||
let show_excluded_uuids = $state(false);
|
||||
let show_all_meetings = $state(false);
|
||||
|
||||
// Apply exclusion to every meeting — produces the "real" participant list
|
||||
// used by all downstream filters, stats, and display.
|
||||
@@ -141,13 +172,17 @@ let meetings_enriched = $derived<MeetingReportEnriched[]>(
|
||||
// final_participants can be null/undefined if meta_json.participants was null in the API response
|
||||
const all_participants: MeetingParticipant[] = m.final_participants ?? [];
|
||||
const real_participants = all_participants.filter((p) => {
|
||||
if (show_excluded_uuids) return true;
|
||||
const participant_uuid = normalize_uuid(p.novi_uuid);
|
||||
if (participant_uuid && exclude_uuid_set.has(participant_uuid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const participant_name = normalize_meeting_name(p.displayName);
|
||||
if (exclude_name_set.has(participant_name)) {
|
||||
if (
|
||||
exclude_name_set.has(participant_name) ||
|
||||
temp_excluded_name_set.has(participant_name)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -174,7 +209,9 @@ let filter_date_to = $state(default_filter_date_to);
|
||||
let filters_are_modified = $derived(
|
||||
filter_real_only ||
|
||||
filter_min_participants !== 0 ||
|
||||
filter_room_name !== '' ||
|
||||
(filter_room_name !== '' && $ae_loc.edit_mode) ||
|
||||
show_excluded_uuids ||
|
||||
show_all_meetings ||
|
||||
filter_date_from !== default_filter_date_from ||
|
||||
filter_date_to !== default_filter_date_to
|
||||
);
|
||||
@@ -183,6 +220,8 @@ function reset_filters() {
|
||||
filter_real_only = false;
|
||||
filter_min_participants = 0;
|
||||
filter_room_name = '';
|
||||
show_excluded_uuids = false;
|
||||
show_all_meetings = false;
|
||||
filter_date_from = default_filter_date_from;
|
||||
filter_date_to = default_filter_date_to;
|
||||
}
|
||||
@@ -214,7 +253,7 @@ function compute_end_time(start_time: string, duration: string): string {
|
||||
// All counts and thresholds use real_participant_count (post-exclusion).
|
||||
let meetings_filtered = $derived.by(() => {
|
||||
return meetings_enriched.filter((m) => {
|
||||
if (known_meeting_set.size > 0) {
|
||||
if (!show_all_meetings && known_meeting_set.size > 0) {
|
||||
if (!known_meeting_set.has(normalize_meeting_name(m.room_name))) {
|
||||
return false;
|
||||
}
|
||||
@@ -224,11 +263,14 @@ let meetings_filtered = $derived.by(() => {
|
||||
if (m.real_participant_count < 2 && dur_secs <= 300) return false;
|
||||
}
|
||||
if (m.real_participant_count < filter_min_participants) return false;
|
||||
if (
|
||||
filter_room_name &&
|
||||
!m.room_name?.toLowerCase().includes(filter_room_name.toLowerCase())
|
||||
)
|
||||
return false;
|
||||
if ($ae_loc.edit_mode && filter_room_name) {
|
||||
if (
|
||||
!m.room_name
|
||||
?.toLowerCase()
|
||||
.includes(filter_room_name.toLowerCase())
|
||||
)
|
||||
return false;
|
||||
}
|
||||
if (filter_date_from) {
|
||||
if (Date.parse(m.start_time) < Date.parse(filter_date_from))
|
||||
return false;
|
||||
@@ -475,6 +517,25 @@ function export_json() {
|
||||
>Real meetings only</span>
|
||||
</label>
|
||||
<div class="bg-surface-200-800 hidden h-8 w-px self-end sm:block"></div>
|
||||
{#if $ae_loc.edit_mode}
|
||||
<label class="flex cursor-pointer items-center gap-2 self-end pb-1.5">
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={show_excluded_uuids}
|
||||
class="checkbox checkbox-sm" />
|
||||
<span class="text-sm font-medium whitespace-nowrap"
|
||||
>Show excluded IDs</span>
|
||||
</label>
|
||||
<label class="flex cursor-pointer items-center gap-2 self-end pb-1.5">
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={show_all_meetings}
|
||||
class="checkbox checkbox-sm" />
|
||||
<span class="text-sm font-medium whitespace-nowrap"
|
||||
>Show all meetings</span>
|
||||
</label>
|
||||
<div class="bg-surface-200-800 hidden h-8 w-px self-end sm:block"></div>
|
||||
{/if}
|
||||
<div>
|
||||
<label
|
||||
for="filter_min_p"
|
||||
@@ -488,8 +549,8 @@ function export_json() {
|
||||
bind:value={filter_min_participants}
|
||||
class="border-surface-200-800 bg-surface-50-950 w-20 rounded border px-2 py-1" />
|
||||
</div>
|
||||
<div>
|
||||
{#if $ae_loc.edit_mode}
|
||||
{#if $ae_loc.edit_mode}
|
||||
<div>
|
||||
<label
|
||||
for="filter_room"
|
||||
class="mb-1 block text-xs tracking-wide uppercase opacity-40">
|
||||
@@ -501,8 +562,8 @@ function export_json() {
|
||||
placeholder="Search rooms..."
|
||||
bind:value={filter_room_name}
|
||||
class="border-surface-200-800 bg-surface-50-950 rounded border px-2 py-1" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div>
|
||||
<label
|
||||
for="filter_date_from"
|
||||
@@ -539,6 +600,40 @@ function export_json() {
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if exclude_uuids.length > 0 || known_meetings.length > 0}
|
||||
<div class="bg-surface-100-900 border-surface-200-800 rounded-xl border p-3">
|
||||
<div class="mb-2 text-xs tracking-wide uppercase opacity-50">
|
||||
Active Exclusions
|
||||
</div>
|
||||
<div class="grid grid-cols-1 gap-2 md:grid-cols-2">
|
||||
<details class="bg-surface-50-950 rounded-lg border border-dashed border-opacity-30 p-2">
|
||||
<summary class="cursor-pointer list-none font-semibold">
|
||||
Excluded Novi UUIDs ({exclude_uuids.length})
|
||||
</summary>
|
||||
<div class="mt-2 space-y-1 text-xs font-mono">
|
||||
{#each exclude_uuids as uuid (uuid)}
|
||||
<div class="bg-surface-200-800 rounded px-2 py-1">
|
||||
{uuid}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</details>
|
||||
<details class="bg-surface-50-950 rounded-lg border border-dashed border-opacity-30 p-2">
|
||||
<summary class="cursor-pointer list-none font-semibold">
|
||||
Known Meeting Names ({known_meetings.length})
|
||||
</summary>
|
||||
<div class="mt-2 space-y-1 text-xs font-mono">
|
||||
{#each known_meetings as meeting_name (meeting_name)}
|
||||
<div class="bg-surface-200-800 rounded px-2 py-1">
|
||||
{meeting_name}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if meetings_loading}
|
||||
<!-- Loading skeleton -->
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user