Initialized Activity Log IndexedDB infrastructure and refactored Jitsi reports.
Added 'activity_log' table to Dexie 'ae_core_db' (v4) to support local caching of tracking data. Implemented 'process_ae_obj__activity_log_props' with robust timestamp fallbacks. Refactored 'qry__jitsi_report' to follow the Frontier module pattern, ensuring consistent V3 search and local cache synchronization.
This commit is contained in:
@@ -268,4 +268,104 @@ export async function qry__activity_log({
|
||||
|
||||
}
|
||||
|
||||
// Updated 2026-02-16
|
||||
export const properties_to_save = [
|
||||
'id',
|
||||
'activity_log_id',
|
||||
'activity_log_id_random',
|
||||
'account_id',
|
||||
'account_id_random',
|
||||
'person_id',
|
||||
'person_id_random',
|
||||
'user_id',
|
||||
'user_id_random',
|
||||
'external_client_id',
|
||||
'source',
|
||||
'object_type',
|
||||
'object_id',
|
||||
'object_id_random',
|
||||
'name',
|
||||
'action',
|
||||
'action_on_type',
|
||||
'action_on_id',
|
||||
'action_on_id_random',
|
||||
'description',
|
||||
'details',
|
||||
'other_json',
|
||||
'meta_json',
|
||||
'enable',
|
||||
'hide',
|
||||
'priority',
|
||||
'sort',
|
||||
'group',
|
||||
'notes',
|
||||
'created_on',
|
||||
'updated_on',
|
||||
'tmp_sort_1',
|
||||
'tmp_sort_2',
|
||||
'tmp_sort_3'
|
||||
];
|
||||
|
||||
async function _process_generic_props<T extends Record<string, any>>({
|
||||
obj_li,
|
||||
obj_type,
|
||||
log_lvl = 0,
|
||||
specific_processor
|
||||
}: {
|
||||
obj_li: T[];
|
||||
obj_type: string;
|
||||
log_lvl?: number;
|
||||
specific_processor?: (obj: T) => Promise<T> | T;
|
||||
}): Promise<T[]> {
|
||||
if (!obj_li || obj_li.length === 0) return [];
|
||||
|
||||
const processed_obj_li: T[] = [];
|
||||
|
||||
for (const original_obj of obj_li) {
|
||||
let processed_obj = { ...original_obj };
|
||||
|
||||
for (const key in processed_obj) {
|
||||
if (key.endsWith('_random')) {
|
||||
const newKey = key.slice(0, -7);
|
||||
(processed_obj as any)[newKey] = processed_obj[key];
|
||||
}
|
||||
}
|
||||
const randomIdKey = `${obj_type}_id_random`;
|
||||
if (processed_obj[randomIdKey]) {
|
||||
(processed_obj as any).id = processed_obj[randomIdKey];
|
||||
}
|
||||
|
||||
const group = processed_obj.group ?? '0';
|
||||
const priority = processed_obj.priority ? 1 : 0;
|
||||
const sort = processed_obj.sort ?? '0';
|
||||
const updated = processed_obj.updated_on ?? processed_obj.created_on ?? new Date(0).toISOString();
|
||||
const name = processed_obj.name ?? '';
|
||||
|
||||
(processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`;
|
||||
(processed_obj as any).tmp_sort_2 = `${group}_${priority}_${sort}_${name}_${updated}`;
|
||||
|
||||
if (specific_processor) {
|
||||
processed_obj = await Promise.resolve(specific_processor(processed_obj));
|
||||
}
|
||||
|
||||
processed_obj_li.push(processed_obj as T);
|
||||
}
|
||||
|
||||
return processed_obj_li;
|
||||
}
|
||||
|
||||
export async function process_ae_obj__activity_log_props({
|
||||
obj_li,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
obj_li: any[];
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
return _process_generic_props({
|
||||
obj_li,
|
||||
obj_type: 'activity_log',
|
||||
log_lvl
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ import type {
|
||||
ae_SiteDomain,
|
||||
ae_Address,
|
||||
ae_Contact,
|
||||
ae_DataStore
|
||||
ae_DataStore,
|
||||
ae_ActivityLog
|
||||
} from '$lib/types/ae_types';
|
||||
|
||||
// li = list
|
||||
@@ -61,7 +62,7 @@ export interface Person extends ae_Person {
|
||||
address_id_random?: string;
|
||||
}
|
||||
|
||||
// Updated 2026-01-28 - Unified Types and added Data Store
|
||||
// Updated 2026-02-16 - Added Activity Log
|
||||
export class MySubClassedDexie extends Dexie {
|
||||
file!: Table<ae_LocalFile>;
|
||||
person!: Table<Person>;
|
||||
@@ -72,10 +73,11 @@ export class MySubClassedDexie extends Dexie {
|
||||
address!: Table<ae_Address>;
|
||||
contact!: Table<ae_Contact>;
|
||||
data_store!: Table<ae_DataStore>;
|
||||
activity_log!: Table<ae_ActivityLog>;
|
||||
|
||||
constructor() {
|
||||
super('ae_core_db');
|
||||
this.version(3).stores({
|
||||
this.version(4).stores({
|
||||
file: `
|
||||
id, hosted_file_id, hosted_file_id_random,
|
||||
hash_sha256,
|
||||
@@ -138,6 +140,14 @@ export class MySubClassedDexie extends Dexie {
|
||||
[code+for_type+for_id_random],
|
||||
[code+account_id_random+for_type],
|
||||
[code+account_id_random],
|
||||
enable, hide, priority, sort, group, created_on, updated_on`,
|
||||
|
||||
activity_log: `
|
||||
id, activity_log_id, activity_log_id_random,
|
||||
account_id, account_id_random,
|
||||
person_id_random, user_id_random,
|
||||
external_client_id, object_type, object_id_random,
|
||||
name, action,
|
||||
enable, hide, priority, sort, group, created_on, updated_on`
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,61 +1,91 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
import { process_ae_obj__activity_log_props, properties_to_save } from '$lib/ae_core/ae_core__activity_log';
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
|
||||
/**
|
||||
* @description Queries all Jitsi-related activity logs and processes them into a structured report,
|
||||
* grouped by meeting ID.
|
||||
* @param api_cfg The API configuration object.
|
||||
* @param account_id The account ID to query against.
|
||||
* @param enabled Filter by enabled status.
|
||||
* @param hidden Filter by hidden status.
|
||||
* @param limit Maximum number of logs to fetch.
|
||||
* @param try_cache Whether to sync the raw logs to the local activity_log table.
|
||||
* @param log_lvl The logging level.
|
||||
* @returns A structured array of meeting report objects.
|
||||
*/
|
||||
export async function load_jitsi_report({
|
||||
export async function qry__jitsi_report({
|
||||
api_cfg,
|
||||
account_id,
|
||||
enabled = 'all',
|
||||
hidden = 'all',
|
||||
limit = 500,
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
account_id: string;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
limit?: number;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) console.log('*** load_jitsi_report() ***');
|
||||
if (log_lvl) console.log('*** qry__jitsi_report() ***');
|
||||
|
||||
// Step 1: Query all relevant activity logs from the API.
|
||||
const params_json = {
|
||||
or_qry: [
|
||||
{
|
||||
field: 'name',
|
||||
operator: '=',
|
||||
value: 'jitsi_meeting_stats_update'
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
operator: '=',
|
||||
value: 'jitsi_meeting_event'
|
||||
}
|
||||
const search_query = {
|
||||
or: [
|
||||
{ field: 'name', op: 'eq', value: 'jitsi_meeting_stats_update' },
|
||||
{ field: 'name', op: 'eq', value: 'jitsi_meeting_event' },
|
||||
{ field: 'name', op: 'eq', value: 'jitsi_meeting_stats' }
|
||||
],
|
||||
and: [
|
||||
{ field: 'account_id_random', op: 'eq', value: account_id }
|
||||
]
|
||||
};
|
||||
|
||||
const flat_log_list = await api.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
const result = await api.search_ae_obj_v3({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'activity_log',
|
||||
for_obj_type: 'account',
|
||||
for_obj_id: account_id,
|
||||
// use_alt_tbl: true,
|
||||
// use_alt_mdl: true,
|
||||
enabled: 'all',
|
||||
hidden: 'all',
|
||||
limit: 500, // Fetch a reasonable number of recent logs
|
||||
params_json: params_json,
|
||||
search_query,
|
||||
headers: { 'x-account-id': account_id },
|
||||
log_lvl: 2
|
||||
enabled,
|
||||
hidden,
|
||||
limit,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
// Handle potential V3 API envelope
|
||||
let flat_log_list: any[] = [];
|
||||
if (Array.isArray(result)) {
|
||||
flat_log_list = result;
|
||||
} else if (result && typeof result === 'object' && Array.isArray((result as any).data)) {
|
||||
flat_log_list = (result as any).data;
|
||||
}
|
||||
|
||||
if (!flat_log_list || !Array.isArray(flat_log_list) || flat_log_list.length === 0) {
|
||||
if (log_lvl) console.log('No Jitsi activity logs found or error occurred.');
|
||||
return [];
|
||||
}
|
||||
|
||||
// Frontier Standard: Process and Save to local cache
|
||||
if (try_cache) {
|
||||
const processed_obj_li = await process_ae_obj__activity_log_props({
|
||||
obj_li: flat_log_list,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_core,
|
||||
table_name: 'activity_log',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
}
|
||||
|
||||
// Step 2: Process the flat list into a structured report.
|
||||
const meetings = new Map<string, any>();
|
||||
|
||||
@@ -112,3 +142,5 @@ export async function load_jitsi_report({
|
||||
|
||||
return final_report;
|
||||
}
|
||||
|
||||
export const load_jitsi_report = qry__jitsi_report;
|
||||
|
||||
Reference in New Issue
Block a user