Cleaning up and removing old legacy code and files
This commit is contained in:
@@ -1,229 +0,0 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { get_object } from './api_get_object';
|
||||
|
||||
// The lookup "obj_type" should broken out into a separate function. - 2024-08-07
|
||||
// Updated 2023-11-15
|
||||
export async function get_ae_obj_li_for_obj_id_crud({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
for_obj_type,
|
||||
for_obj_id, // NOTE: Changed 2023-12-06 to no longer required
|
||||
use_alt_table = false,
|
||||
use_alt_base = false,
|
||||
// inc = {},
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
order_by_li = null,
|
||||
limit = 999999,
|
||||
offset = 0,
|
||||
// key,
|
||||
// jwt = null,
|
||||
headers = {},
|
||||
params_json = null, // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the API endpoint. Example: { "fulltext_search": { "default_qry_str": "Search string for default", "address_default_qry_str": "Search string for address", "contact_1_default_qry_str": "Search string for contact_1" } }
|
||||
// json_obj = null, // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
|
||||
params = {},
|
||||
return_meta = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
obj_type: string;
|
||||
for_obj_type: null | string;
|
||||
for_obj_id?: string;
|
||||
use_alt_table?: boolean;
|
||||
use_alt_base?: boolean;
|
||||
// inc?: key_val
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
order_by_li?: any;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
// key: string,
|
||||
// jwt?: string,
|
||||
headers?: any;
|
||||
params_json?: any;
|
||||
// json_obj?: any,
|
||||
params?: key_val;
|
||||
return_meta?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** get_ae_obj_li_for_obj_id_crud() *** [${obj_type}]`);
|
||||
}
|
||||
|
||||
// data = {};
|
||||
// data['super_key'] = key;
|
||||
// data['jwt'] = jwt;
|
||||
// NOTE: The key and or JWT should be in the header of the DELETE, GET, PATCH, POST
|
||||
|
||||
// const endpoint = `/crud/${obj_type}/list`;
|
||||
|
||||
let endpoint = '';
|
||||
if (obj_type == 'account') {
|
||||
endpoint = `/crud/account/list`;
|
||||
} else if (obj_type == 'address') {
|
||||
endpoint = `/crud/address/list`;
|
||||
} else if (obj_type == 'archive') {
|
||||
endpoint = `/crud/archive/list`;
|
||||
} else if (obj_type == 'archive_content') {
|
||||
endpoint = `/crud/archive/content/list`;
|
||||
} else if (obj_type == 'contact') {
|
||||
endpoint = `/crud/contact/list`;
|
||||
} else if (obj_type == 'data_store') {
|
||||
endpoint = `/crud/data_store/list`;
|
||||
} else if (obj_type == 'event') {
|
||||
endpoint = `/crud/event/list`;
|
||||
} else if (obj_type == 'event_abstract') {
|
||||
endpoint = `/crud/event/abstract/list`;
|
||||
} else if (obj_type == 'event_badge') {
|
||||
endpoint = `/crud/event/badge/list`;
|
||||
} else if (obj_type == 'event_device') {
|
||||
endpoint = `/crud/event/device/list`;
|
||||
} else if (obj_type == 'event_exhibit') {
|
||||
endpoint = `/crud/event/exhibit/list`;
|
||||
} else if (obj_type == 'event_exhibit_tracking') {
|
||||
endpoint = `/crud/event/exhibit/tracking/list`;
|
||||
} else if (obj_type == 'event_file') {
|
||||
endpoint = `/crud/event/file/list`;
|
||||
} else if (obj_type == 'event_location') {
|
||||
endpoint = `/crud/event/location/list`;
|
||||
} else if (obj_type == 'event_person') {
|
||||
endpoint = `/crud/event/person/list`;
|
||||
} else if (obj_type == 'event_presentation') {
|
||||
endpoint = `/crud/event/presentation/list`;
|
||||
} else if (obj_type == 'event_presenter') {
|
||||
endpoint = `/crud/event/presenter/list`;
|
||||
} else if (obj_type == 'event_session') {
|
||||
endpoint = `/crud/event/session/list`;
|
||||
} else if (obj_type == 'event_track') {
|
||||
endpoint = `/crud/event/track/list`;
|
||||
} else if (obj_type == 'grant') {
|
||||
endpoint = `/crud/grant/list`;
|
||||
} else if (obj_type == 'hosted_file') {
|
||||
endpoint = `/crud/hosted_file/list`;
|
||||
} else if (obj_type == 'journal') {
|
||||
endpoint = `/crud/journal/list`;
|
||||
} else if (obj_type == 'journal_entry') {
|
||||
endpoint = `/crud/journal/entry/list`;
|
||||
} else if (obj_type == 'order') {
|
||||
endpoint = `/crud/order/list`;
|
||||
} else if (obj_type == 'order_line') {
|
||||
endpoint = `/crud/order/line/list`;
|
||||
} else if (obj_type == 'page') {
|
||||
endpoint = `/crud/page/list`;
|
||||
} else if (obj_type == 'person') {
|
||||
endpoint = `/crud/person/list`;
|
||||
} else if (obj_type == 'post') {
|
||||
endpoint = `/crud/post/list`;
|
||||
} else if (obj_type == 'post_comment') {
|
||||
endpoint = `/crud/post/comment/list`;
|
||||
} else if (obj_type == 'site') {
|
||||
endpoint = `/crud/site/list`;
|
||||
} else if (obj_type == 'sponsorship_cfg') {
|
||||
endpoint = `/crud/sponsorship/cfg/list`;
|
||||
} else if (obj_type == 'sponsorship') {
|
||||
endpoint = `/crud/sponsorship/list`;
|
||||
// } else if (obj_type == 'user') {
|
||||
// endpoint = `/crud/user/list`;
|
||||
} else if (obj_type == 'lu' && for_obj_type == 'country_subdivision') {
|
||||
endpoint = `/crud/lu/country_subdivision/list`;
|
||||
for_obj_type = null;
|
||||
} else if (obj_type == 'lu' && for_obj_type == 'country') {
|
||||
endpoint = `/crud/lu/country/list`;
|
||||
for_obj_type = null;
|
||||
} else if (obj_type == 'lu' && for_obj_type == 'time_zone') {
|
||||
endpoint = `/crud/lu/time_zone/list`;
|
||||
for_obj_type = null;
|
||||
} else {
|
||||
console.log(`Unknown object type: ${obj_type}`);
|
||||
return false;
|
||||
}
|
||||
if (log_lvl) {
|
||||
console.log('Endpoint:', endpoint);
|
||||
}
|
||||
|
||||
if (for_obj_type) {
|
||||
params['for_obj_type'] = for_obj_type;
|
||||
}
|
||||
if (for_obj_id) {
|
||||
params['for_obj_id'] = for_obj_id;
|
||||
}
|
||||
|
||||
params['use_alt_table'] = use_alt_table;
|
||||
params['use_alt_base'] = use_alt_base;
|
||||
|
||||
/* Need to deal with inc params here */
|
||||
|
||||
const allowed_enabled_list = ['all', 'enabled', 'not_enabled'];
|
||||
if (allowed_enabled_list.includes(enabled)) {
|
||||
params['enabled'] = enabled;
|
||||
}
|
||||
|
||||
const allowed_hidden_list = ['all', 'hidden', 'not_hidden'];
|
||||
if (allowed_hidden_list.includes(hidden)) {
|
||||
params['hidden'] = hidden;
|
||||
}
|
||||
|
||||
// NOTE: The order_by_li variable is in the "headers" because if is a the URL GET params do not handle multiple values very well. Maybe base64 encore in the future or something? Reminder that GET requests should not have a body (no JSON).
|
||||
// NOTE: The order_by_li should be a key value pair of the property/DB field to sort and how to sort (ASC or DESC)
|
||||
if (order_by_li) {
|
||||
if (log_lvl) {
|
||||
console.log('Order By:', order_by_li);
|
||||
}
|
||||
headers['order_by_li'] = order_by_li;
|
||||
}
|
||||
|
||||
if (limit >= 0) {
|
||||
params['limit'] = limit;
|
||||
}
|
||||
|
||||
if (offset >= 0) {
|
||||
params['offset'] = offset;
|
||||
}
|
||||
|
||||
if (params_json) {
|
||||
// NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
|
||||
// Max characters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
|
||||
if (log_lvl) {
|
||||
console.log('JSON Object:', params_json);
|
||||
console.log(JSON.stringify(params_json));
|
||||
}
|
||||
// NOTE: "jp" stands for "JSON Params"
|
||||
params['jp'] = encodeURIComponent(JSON.stringify(params_json));
|
||||
if (params['jp'].length > 2083) {
|
||||
console.log(
|
||||
`The JSON object is too large to be used as a GET parameter. The overall max URL length is 2083 characters. Please use the POST endpoint instead. Length = ${params['jp'].length} [THIS DOES NOT EXIST YET]`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// if (json_obj) {
|
||||
// // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
|
||||
// // Max characters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
|
||||
// console.log('JSON Object:', json_obj);
|
||||
// params['json_str'] = encodeURIComponent(JSON.stringify(json_obj));
|
||||
// if (params['json_str'].length > 2083) {
|
||||
// console.log(`The JSON object is too large to be used as a GET parameter. The overall max URL length is 2083 characters. Please use the POST endpoint instead. Length = ${params['json_str'].length} [THIS DOES NOT EXIST YET]`);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('Params:', params);
|
||||
}
|
||||
|
||||
const object_li_get_promise = await get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
headers: headers,
|
||||
params: params,
|
||||
return_meta: return_meta,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log(object_li_get_promise);
|
||||
}
|
||||
|
||||
return object_li_get_promise;
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { get_object } from './api_get_object';
|
||||
|
||||
// Refactored 2025-11-13 to use a lookup map for endpoints.
|
||||
const objTypeToEndpointMap: Record<string, string> = {
|
||||
account: '/crud/account/list',
|
||||
address: '/crud/address/list',
|
||||
archive: '/crud/archive/list',
|
||||
archive_content: '/crud/archive/content/list',
|
||||
activity_log: '/crud/activity_log/list',
|
||||
contact: '/crud/contact/list',
|
||||
data_store: '/crud/data_store/list',
|
||||
event: '/crud/event/list',
|
||||
event_abstract: '/crud/event/abstract/list',
|
||||
event_badge: '/crud/event/badge/list',
|
||||
event_badge_template: '/crud/event/badge/template/list',
|
||||
event_device: '/crud/event/device/list',
|
||||
event_exhibit: '/crud/event/exhibit/list',
|
||||
event_exhibit_tracking: '/crud/event/exhibit/tracking/list',
|
||||
event_file: '/crud/event/file/list',
|
||||
event_location: '/crud/event/location/list',
|
||||
event_person: '/crud/event/person/list',
|
||||
event_presentation: '/crud/event/presentation/list',
|
||||
event_presenter: '/crud/event/presenter/list',
|
||||
event_session: '/crud/event/session/list',
|
||||
event_track: '/crud/event/track/list',
|
||||
grant: '/crud/grant/list',
|
||||
hosted_file: '/crud/hosted_file/list',
|
||||
journal: '/crud/journal/list',
|
||||
journal_entry: '/crud/journal/entry/list',
|
||||
order: '/crud/order/list',
|
||||
order_line: '/crud/order/line/list',
|
||||
page: '/crud/page/list',
|
||||
person: '/crud/person/list',
|
||||
post: '/crud/post/list',
|
||||
post_comment: '/crud/post/comment/list',
|
||||
site: '/crud/site/list',
|
||||
sponsorship_cfg: '/crud/sponsorship/cfg/list',
|
||||
sponsorship: '/crud/sponsorship/list',
|
||||
// user: '/crud/user/list',
|
||||
'lu-country_subdivision': '/crud/lu/country_subdivision/list',
|
||||
'lu-country': '/crud/lu/country/list',
|
||||
'lu-time_zone': '/crud/lu/time_zone/list'
|
||||
};
|
||||
|
||||
function getEndpointForObjType(obj_type: string, for_obj_type?: string): string {
|
||||
if (obj_type === 'lu' && for_obj_type) {
|
||||
const key = `lu-${for_obj_type}`;
|
||||
const endpoint = objTypeToEndpointMap[key];
|
||||
if (endpoint) return endpoint;
|
||||
}
|
||||
|
||||
const endpoint = objTypeToEndpointMap[obj_type];
|
||||
if (endpoint) return endpoint;
|
||||
|
||||
throw new Error(`Unknown object type: ${obj_type}`);
|
||||
}
|
||||
|
||||
type OrderBy = { [key: string]: 'ASC' | 'DESC' };
|
||||
|
||||
interface GetAeObjLiForObjIdCrudV2Params {
|
||||
api_cfg: any; // Consider defining a specific type for api_cfg
|
||||
obj_type: string;
|
||||
for_obj_type: string;
|
||||
for_obj_id?: string;
|
||||
use_alt_tbl?: boolean | string;
|
||||
use_alt_mdl?: boolean | string;
|
||||
use_alt_exp?: boolean | string;
|
||||
inc?: key_val;
|
||||
enabled?: 'all' | 'enabled' | 'not_enabled';
|
||||
hidden?: 'all' | 'hidden' | 'not_hidden';
|
||||
order_by_li?: OrderBy | OrderBy[] | null;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
headers?: Record<string, string>;
|
||||
params_json?: any;
|
||||
params?: key_val;
|
||||
log_lvl?: number;
|
||||
}
|
||||
|
||||
export async function get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
for_obj_type,
|
||||
for_obj_id,
|
||||
use_alt_tbl = false,
|
||||
use_alt_mdl = false,
|
||||
use_alt_exp = false,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
order_by_li = null,
|
||||
limit = 999999,
|
||||
offset = 0,
|
||||
headers = {},
|
||||
params_json = null,
|
||||
params = {},
|
||||
log_lvl = 0
|
||||
}: GetAeObjLiForObjIdCrudV2Params) {
|
||||
if (log_lvl) {
|
||||
console.log('*** get_ae_obj_li_for_obj_id_crud_v2() ***');
|
||||
}
|
||||
|
||||
try {
|
||||
const endpoint = `/v2${getEndpointForObjType(obj_type, for_obj_type)}`;
|
||||
if (log_lvl) {
|
||||
console.log('Endpoint:', endpoint);
|
||||
}
|
||||
|
||||
// We need to remove a few parameters from the params object that are not allowed.
|
||||
delete params['qry__enabled'];
|
||||
delete params['qry__hidden'];
|
||||
delete params['qry__limit'];
|
||||
delete params['qry__offset'];
|
||||
|
||||
if (for_obj_type) params['for_obj_type'] = for_obj_type;
|
||||
if (for_obj_id) params['for_obj_id'] = for_obj_id;
|
||||
|
||||
if (use_alt_tbl === true) params['tbl_alt'] = 'alt';
|
||||
if (use_alt_mdl === true) params['mdl_alt'] = 'alt';
|
||||
if (use_alt_exp === true) params['exp_alt'] = 'alt';
|
||||
|
||||
const allowed_enabled_list = ['all', 'enabled', 'not_enabled'];
|
||||
if (allowed_enabled_list.includes(enabled)) {
|
||||
params['enabled'] = enabled;
|
||||
}
|
||||
|
||||
const allowed_hidden_list = ['all', 'hidden', 'not_hidden'];
|
||||
if (allowed_hidden_list.includes(hidden)) {
|
||||
params['hidden'] = hidden;
|
||||
}
|
||||
|
||||
// NOTE: The order_by_li variable is in the "headers" because URL GET params do not handle complex objects very well.
|
||||
if (order_by_li) {
|
||||
headers['order_by_li'] = JSON.stringify(order_by_li);
|
||||
}
|
||||
|
||||
if (limit > 0) params['limit'] = limit;
|
||||
if (offset > 0) params['offset'] = offset;
|
||||
|
||||
if (params_json) {
|
||||
// NOTE: "jp" stands for "JSON Params". This is a JSON object that needs to be safely converted to a string for the params.
|
||||
// Max characters for a GET request is ~2000. This is a limitation of the browser.
|
||||
const json_params_str = encodeURIComponent(JSON.stringify(params_json));
|
||||
if (json_params_str.length > 2083) {
|
||||
// Using console.error instead of throwing an error to avoid crashing the app for a known limitation.
|
||||
console.error(
|
||||
`The JSON object is too large to be used as a GET parameter. Max length is 2083 characters. Length = ${json_params_str.length}`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
params['jp'] = json_params_str;
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('Params:', params);
|
||||
}
|
||||
|
||||
const object_li_get_promise = await get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
headers: headers,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log(object_li_get_promise);
|
||||
}
|
||||
|
||||
return object_li_get_promise;
|
||||
} catch (error) {
|
||||
console.error('Error in get_ae_obj_li_for_obj_id_crud_v2:', error);
|
||||
return false; // Or handle the error as appropriate
|
||||
}
|
||||
}
|
||||
@@ -1,524 +0,0 @@
|
||||
import axios from 'axios';
|
||||
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
export let temp_get_blob_percent_completed = 0;
|
||||
// export let get_blob_percent_completed = readable(temp_get_blob_percent_completed);
|
||||
export const get_blob_percent_completed = temp_get_blob_percent_completed;
|
||||
|
||||
export let temp_get_object_percent_completed = 0;
|
||||
// export let get_object_percent_completed = readable(temp_get_object_percent_completed);
|
||||
export const get_object_percent_completed = temp_get_object_percent_completed;
|
||||
|
||||
// Updated 2024-05-23
|
||||
export const get_object = async function get_object({
|
||||
api_cfg = null,
|
||||
endpoint = '',
|
||||
headers = {},
|
||||
params = {},
|
||||
data = {},
|
||||
timeout = 60000,
|
||||
return_meta = false,
|
||||
return_blob = false,
|
||||
filename = '',
|
||||
auto_download = false,
|
||||
as_list = false,
|
||||
// The task_id value should be a random string that is unique to the task. This is used to identify the task in the message event.
|
||||
task_id = crypto.randomUUID(),
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
endpoint: string;
|
||||
headers?: any;
|
||||
params?: any;
|
||||
data?: any;
|
||||
timeout?: number;
|
||||
return_meta?: boolean;
|
||||
return_blob?: boolean;
|
||||
filename?: null | string;
|
||||
auto_download?: boolean;
|
||||
as_list?: boolean;
|
||||
task_id?: string;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** get_object() *** Endpoint: ${endpoint} AE Task ID: ${task_id}`);
|
||||
console.log('Params:', params);
|
||||
if (log_lvl > 1) {
|
||||
console.log('Data:', data);
|
||||
console.log(`Base URL: ${api_cfg['base_url']}; Timeout: ${timeout}`);
|
||||
console.log('API Config:', api_cfg);
|
||||
}
|
||||
if (log_lvl > 2) {
|
||||
console.log(
|
||||
`Return Meta: ${return_meta}; Return Blob: ${return_blob}; Filename: ${filename}; Auto Download: ${auto_download}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!api_cfg) {
|
||||
console.log('No API Config was provided. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
const axios_api = axios.create({
|
||||
baseURL: api_cfg['base_url'],
|
||||
timeout: timeout // in milliseconds; 60000 = 60 seconds
|
||||
/* other custom settings */
|
||||
});
|
||||
axios_api.defaults.headers = api_cfg['headers'];
|
||||
if (log_lvl) {
|
||||
console.log('axios_api.defaults.headers:', axios_api.defaults.headers);
|
||||
console.log('Additional headers:', headers);
|
||||
}
|
||||
|
||||
// console.log('Clean the headers. No _underscores_!')
|
||||
const headers_cleaned: key_val = {};
|
||||
for (const prop in headers) {
|
||||
// No underscores allowed in the header parameters!
|
||||
const prop_cleaned = prop.replaceAll('_', '-');
|
||||
|
||||
// The value must be a string for the header!
|
||||
if (typeof headers[prop] != 'string') {
|
||||
headers[prop] = JSON.stringify(headers[prop]);
|
||||
}
|
||||
|
||||
headers_cleaned[prop_cleaned] = headers[prop];
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`${prop_cleaned}: ${headers_cleaned[prop_cleaned]}`);
|
||||
}
|
||||
}
|
||||
headers = headers_cleaned;
|
||||
if (log_lvl) {
|
||||
console.log('All headers cleaned:', headers);
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('URL params:');
|
||||
}
|
||||
for (const prop in params) {
|
||||
if (log_lvl > 1) {
|
||||
console.log(`URL param: ${prop}: ${params[prop]}`);
|
||||
}
|
||||
if (params[prop] === null) {
|
||||
params[prop] = 'null';
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the case where there is no Blob expected to be returned. Mainly JSON and text data.
|
||||
if (!return_blob) {
|
||||
const response_data_promise = await axios_api
|
||||
.get(endpoint, {
|
||||
headers: headers,
|
||||
params: params,
|
||||
onDownloadProgress: (progressEvent) => {
|
||||
const total = progressEvent.total ?? 0;
|
||||
const percent_completed = total > 0 ? Math.round((progressEvent.loaded * 100) / total) : 0;
|
||||
if (log_lvl > 1) {
|
||||
console.log(
|
||||
'GET Data Progress:',
|
||||
progressEvent.progress,
|
||||
'Total:',
|
||||
total,
|
||||
'Loaded:',
|
||||
progressEvent.loaded,
|
||||
'Percent Completed',
|
||||
percent_completed
|
||||
);
|
||||
}
|
||||
|
||||
temp_get_object_percent_completed = percent_completed;
|
||||
|
||||
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
|
||||
try {
|
||||
// Check if window is defined. This is to prevent errors in SvelteKit.
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_data',
|
||||
status: 'downloading',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: total,
|
||||
size_loaded: progressEvent.loaded,
|
||||
percent_completed: percent_completed
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`GET Response: status=${response.status} statusText=${response.statusText} baseURL=${response.config.baseURL} url=${response.config.url} method=${response.config.method} headers=${response.config.headers} params=${JSON.stringify(response.config.params)}`
|
||||
);
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log('GET Response:', response);
|
||||
}
|
||||
|
||||
// Post file download message
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_data',
|
||||
status: 'complete',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: 0,
|
||||
size_loaded: 0,
|
||||
percent_completed: 100
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
|
||||
if (!Array.isArray(response.data['data']) && as_list) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
'Data result is a dictionary/object, not an array/list. Forcing return as an array/list'
|
||||
);
|
||||
}
|
||||
const return_data = [];
|
||||
return_data.push(response.data['data']);
|
||||
return return_data;
|
||||
} else if (response.data['data']) {
|
||||
const return_data = response.data['data'];
|
||||
if (log_lvl) {
|
||||
if (Array.isArray(return_data)) {
|
||||
console.log(
|
||||
`Data result is an array/list. Array length: ${return_data.length}`
|
||||
);
|
||||
} else {
|
||||
console.log(`Data result is a dictionary/object, not an array/list.`);
|
||||
}
|
||||
}
|
||||
return return_data;
|
||||
} else {
|
||||
const return_data = response.data;
|
||||
if (log_lvl) {
|
||||
if (Array.isArray(return_data)) {
|
||||
console.log(
|
||||
`Not a standard response from Aether's API. Data result is an array/list. Array length: ${return_data.length}`
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`Not a standard response from Aether's API. Data result is a dictionary/object, not an array/list.`
|
||||
);
|
||||
}
|
||||
}
|
||||
return return_data;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
// Handle the common and expected 404 "error" first
|
||||
if (error.response && error.response.status === 404) {
|
||||
if (log_lvl) {
|
||||
console.log('The response was a 404 not found "error". Returning null.');
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log(error.response);
|
||||
}
|
||||
if (log_lvl > 2) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
// Post file download message
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_data',
|
||||
status: 'complete',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: 0,
|
||||
size_loaded: 0,
|
||||
percent_completed: 0
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
return null; // Returning null since there were no results
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Base URL: ${api_cfg['base_url']} | Endpoint: ${endpoint}`);
|
||||
console.log('Error Message:', error.message); // Is this needed here or below in the in the else portion???
|
||||
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code that falls out of the range of 2xx
|
||||
console.log('Error Response Data', error.response.data);
|
||||
console.log('Error Response Status', error.response.status);
|
||||
console.log('Error Response Headers', error.response.headers);
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js
|
||||
if (log_lvl > 1) {
|
||||
console.log('Error Request', error.request);
|
||||
}
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.log('Error Message', error.message);
|
||||
}
|
||||
}
|
||||
if (log_lvl > 2) {
|
||||
console.log('Error:', error);
|
||||
console.log(error.config);
|
||||
}
|
||||
|
||||
if (error.code === 'ECONNABORTED') {
|
||||
// Timeout Error (You can implement retry here where suitable)
|
||||
console.log('Timeout Error: ', error.message);
|
||||
}
|
||||
if (log_lvl) {
|
||||
console.log('The response was an error. Returning false.');
|
||||
}
|
||||
|
||||
return false; // Returning false since something may have gone wrong. This includes timeouts. Also more in line with what the API returns.
|
||||
// return error;
|
||||
});
|
||||
|
||||
if (log_lvl > 1) {
|
||||
// console.log(`Response Data: ${response_data_promise}`);
|
||||
console.log(`Response Data:`, response_data_promise);
|
||||
// console.log(response_data_promise);
|
||||
}
|
||||
if (response_data_promise) {
|
||||
// The most common and expected response.
|
||||
// console.log('Returning result. This is generally expected.');
|
||||
return response_data_promise;
|
||||
} else if (response_data_promise === null) {
|
||||
// Less common, but expected response if no results were returned.
|
||||
if (log_lvl) {
|
||||
console.log('Returning null. This is expected if no results were found. (404)');
|
||||
}
|
||||
return response_data_promise;
|
||||
} else if (response_data_promise === false) {
|
||||
// Not common, but expected response if the request to the API had an issue.
|
||||
console.log('Returning false. There may have been an issue with this request.');
|
||||
return response_data_promise;
|
||||
} else {
|
||||
// This generally should not happen. It likely means the query was bad or an API issue.
|
||||
console.log('Returning (JSON/text) unknown. This should not happen in most cases.');
|
||||
Promise.reject(new Error('fail')).then(resolved, rejected);
|
||||
}
|
||||
|
||||
// Handle the case where a Blob is expected to be returned.
|
||||
} else {
|
||||
// console.log('Expecting a Blob to be returned...');
|
||||
|
||||
const response_data_promise = await axios_api
|
||||
.get(endpoint, {
|
||||
params: params,
|
||||
responseType: 'blob',
|
||||
onDownloadProgress: (progressEvent) => {
|
||||
const total = progressEvent.total ?? 0;
|
||||
const percent_completed = total > 0 ? Math.round((progressEvent.loaded * 100) / total) : 0;
|
||||
console.log(
|
||||
'GET Blob Progress:',
|
||||
progressEvent.progress,
|
||||
'Total:',
|
||||
total,
|
||||
'Loaded:',
|
||||
progressEvent.loaded,
|
||||
'Percent Completed',
|
||||
percent_completed
|
||||
);
|
||||
|
||||
temp_get_blob_percent_completed = percent_completed;
|
||||
|
||||
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_blob',
|
||||
status: 'downloading',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: total,
|
||||
size_loaded: progressEvent.loaded,
|
||||
percent_completed: percent_completed
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`GET (blob) Response: status=${response.status} statusText=${response.statusText} baseURL=${response.config.baseURL} url=${response.config.url} method=${response.config.method} headers=${response.config.headers} params=${response.config.params}`
|
||||
);
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log('GET (blob) Response:', response);
|
||||
}
|
||||
|
||||
const { data, headers } = response;
|
||||
|
||||
// Careful if this download filename needs to be changed to a different file extension. The browser/client may not know how to handle it.
|
||||
if (filename) {
|
||||
} else if (headers['content-disposition']) {
|
||||
filename = headers['content-disposition'].replace(/\w+;filename=(.*)/, '$1');
|
||||
} else {
|
||||
filename = 'unknown_file.ext';
|
||||
}
|
||||
|
||||
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_blob',
|
||||
status: 'complete',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: 0,
|
||||
size_loaded: 0,
|
||||
percent_completed: 100
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
|
||||
if (auto_download) {
|
||||
if (log_lvl) {
|
||||
console.log(`Auto Download: ${filename}`);
|
||||
}
|
||||
const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.setAttribute('download', filename || 'download');
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
return true;
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
// Handle the common and expected 404 "error" first
|
||||
if (error.response && error.response.status === 404) {
|
||||
if (log_lvl) {
|
||||
console.log('The response was a 404 not found "error". Returning null.');
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log(error.response);
|
||||
}
|
||||
if (log_lvl > 2) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
// Post file download message
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_blob',
|
||||
status: 'complete',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: 0,
|
||||
size_loaded: 0,
|
||||
percent_completed: 0
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
return null; // Returning null since there were no results
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Base URL: ${api_cfg['base_url']} | Endpoint: ${endpoint}`);
|
||||
console.log('Error Message:', error.message); // Is this needed here or below in the in the else portion???
|
||||
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code that falls out of the range of 2xx
|
||||
console.log('Error Response Data', error.response.data);
|
||||
console.log('Error Response Status', error.response.status);
|
||||
console.log('Error Response Headers', error.response.headers);
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js
|
||||
if (log_lvl > 1) {
|
||||
console.log('Error Request', error.request);
|
||||
}
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.log('Error Message', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (error.code === 'ECONNABORTED') {
|
||||
// Timeout Error (You can implement retry here where suitable)
|
||||
console.log('Timeout Error: ', error.message);
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('The response was an error. Returning false.');
|
||||
}
|
||||
|
||||
return false; // Returning false since something may have gone wrong. This includes timeouts. Also more in line with what the API returns.
|
||||
// return error;
|
||||
});
|
||||
|
||||
if (response_data_promise) {
|
||||
// The most common and expected response.
|
||||
// console.log('Returning result. This is generally expected.');
|
||||
// let test_blob = new Blob([response_data_promise.data]);
|
||||
// console.log(test_blob);
|
||||
// return test_blob;
|
||||
// console.log(response_data_promise.blob());
|
||||
return response_data_promise;
|
||||
} else if (response_data_promise === null) {
|
||||
// Less common, but expected response if no results were returned.
|
||||
if (log_lvl) {
|
||||
console.log('Returning null. This is expected if no results were found. (404)');
|
||||
}
|
||||
return response_data_promise;
|
||||
} else if (response_data_promise === false) {
|
||||
// Not common, but expected response if the request to the API had an issue.
|
||||
console.log('Returning false. There may have been an issue with this request.');
|
||||
return response_data_promise;
|
||||
} else {
|
||||
// This generally should not happen. It likely means the query was bad or an API issue.
|
||||
console.log('Returning (blob) unknown. This should not happen in most cases.');
|
||||
Promise.reject(new Error('fail')).then(resolved, rejected);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function resolved(result: any) {
|
||||
console.log('Resolved');
|
||||
}
|
||||
|
||||
function rejected(result: any) {
|
||||
console.error(result);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
import { get_ae_obj_li_for_obj_id_crud_v2 } from '$lib/ae_api/api_get__crud_obj_li_v2';
|
||||
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
import { db_events } from '$lib/ae_events/db_events';
|
||||
@@ -490,10 +489,10 @@ export async function update_ae_obj__event({
|
||||
// Updated 2026-01-21
|
||||
/**
|
||||
* Unified Search for Events (V3 API)
|
||||
*
|
||||
*
|
||||
* STRATEGY: Hybrid Search/Filter
|
||||
* 1. Server-side (V3 Search): Used for text search (qry_str) to reduce payload.
|
||||
* 2. Client-side (Filter Layer): Handles all other filters (Type, Location, Person)
|
||||
* 2. Client-side (Filter Layer): Handles all other filters (Type, Location, Person)
|
||||
* to ensure correct inclusive OR logic and stable ID matching.
|
||||
*/
|
||||
export async function search__event({
|
||||
@@ -548,13 +547,13 @@ export async function search__event({
|
||||
params['lk_qry'] = { 'default_qry_str': qry_str.trim() };
|
||||
|
||||
if (for_obj_id) {
|
||||
// V3 Standard: Use random string ID for body filters.
|
||||
// V3 Standard: Use random string ID for body filters.
|
||||
// The API resolves this to the integer column automatically.
|
||||
search_query.and.push({ field: `${for_obj_type}_id_random`, op: 'eq', value: for_obj_id });
|
||||
}
|
||||
|
||||
// NOTE: We do NOT push 'physical' and 'virtual' to the server-side query here.
|
||||
// The V3 Search API uses AND logic for the body, which would exclude
|
||||
// The V3 Search API uses AND logic for the body, which would exclude
|
||||
// meetings that are only physical or only virtual if both filters are active.
|
||||
// We handle this in the Client-side Filter Layer below for correct OR logic.
|
||||
|
||||
@@ -671,131 +670,131 @@ export const qry_ae_obj_li__event = search__event;
|
||||
* This is isolated to prevent V3 migration bugs from affecting Recovery Meetings.
|
||||
*/
|
||||
// Updated 2026-01-20
|
||||
export async function qry_ae_obj_li__event_v2({
|
||||
api_cfg,
|
||||
for_obj_type = 'account',
|
||||
for_obj_id,
|
||||
qry_str,
|
||||
qry_person_id = null,
|
||||
qry_conference = null,
|
||||
qry_physical = null,
|
||||
qry_virtual = null,
|
||||
qry_type = null,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
view = 'default',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
order_by_li = { start_datetime: 'DESC' } as const,
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
for_obj_type?: string;
|
||||
for_obj_id: string;
|
||||
qry_str?: string;
|
||||
qry_person_id?: string | null;
|
||||
qry_conference?: boolean | null;
|
||||
qry_physical?: boolean | null;
|
||||
qry_virtual?: boolean | null;
|
||||
qry_type?: string | null;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled';
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden';
|
||||
view?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: Record<string, 'ASC' | 'DESC'>;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) console.log('*** qry_ae_obj_li__event_v2() ***');
|
||||
// export async function qry_ae_obj_li__event_v2({
|
||||
// api_cfg,
|
||||
// for_obj_type = 'account',
|
||||
// for_obj_id,
|
||||
// qry_str,
|
||||
// qry_person_id = null,
|
||||
// qry_conference = null,
|
||||
// qry_physical = null,
|
||||
// qry_virtual = null,
|
||||
// qry_type = null,
|
||||
// enabled = 'enabled',
|
||||
// hidden = 'not_hidden',
|
||||
// view = 'default',
|
||||
// limit = 99,
|
||||
// offset = 0,
|
||||
// order_by_li = { start_datetime: 'DESC' } as const,
|
||||
// try_cache = true,
|
||||
// log_lvl = 0
|
||||
// }: {
|
||||
// api_cfg: any;
|
||||
// for_obj_type?: string;
|
||||
// for_obj_id: string;
|
||||
// qry_str?: string;
|
||||
// qry_person_id?: string | null;
|
||||
// qry_conference?: boolean | null;
|
||||
// qry_physical?: boolean | null;
|
||||
// qry_virtual?: boolean | null;
|
||||
// qry_type?: string | null;
|
||||
// enabled?: 'enabled' | 'all' | 'not_enabled';
|
||||
// hidden?: 'hidden' | 'all' | 'not_hidden';
|
||||
// view?: string;
|
||||
// limit?: number;
|
||||
// offset?: number;
|
||||
// order_by_li?: Record<string, 'ASC' | 'DESC'>;
|
||||
// try_cache?: boolean;
|
||||
// log_lvl?: number;
|
||||
// }) {
|
||||
// if (log_lvl) console.log('*** qry_ae_obj_li__event_v2() ***');
|
||||
|
||||
const params_json: any = { qry: { and: [] } };
|
||||
// const params_json: any = { qry: { and: [] } };
|
||||
|
||||
if (qry_str) {
|
||||
// Use default_qry_str for searching as requested
|
||||
params_json.qry.and.push({ field: 'default_qry_str', op: 'like', value: `%${qry_str}%` });
|
||||
}
|
||||
// if (qry_str) {
|
||||
// // Use default_qry_str for searching as requested
|
||||
// params_json.qry.and.push({ field: 'default_qry_str', op: 'like', value: `%${qry_str}%` });
|
||||
// }
|
||||
|
||||
const result_li = await get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg,
|
||||
obj_type: 'event',
|
||||
for_obj_type,
|
||||
for_obj_id,
|
||||
enabled,
|
||||
hidden,
|
||||
limit,
|
||||
offset,
|
||||
order_by_li,
|
||||
params_json,
|
||||
log_lvl
|
||||
});
|
||||
// const result_li = await get_ae_obj_li_for_obj_id_crud_v2({
|
||||
// api_cfg,
|
||||
// obj_type: 'event',
|
||||
// for_obj_type,
|
||||
// for_obj_id,
|
||||
// enabled,
|
||||
// hidden,
|
||||
// limit,
|
||||
// offset,
|
||||
// order_by_li,
|
||||
// params_json,
|
||||
// log_lvl
|
||||
// });
|
||||
|
||||
if (!result_li) return [];
|
||||
// if (!result_li) return [];
|
||||
|
||||
const processed_obj_li = await process_ae_obj__event_props({
|
||||
obj_li: result_li,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
// const processed_obj_li = await process_ae_obj__event_props({
|
||||
// obj_li: result_li,
|
||||
// log_lvl: log_lvl
|
||||
// });
|
||||
|
||||
if (try_cache) {
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_events,
|
||||
table_name: 'event',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
}
|
||||
// if (try_cache) {
|
||||
// await db_save_ae_obj_li__ae_obj({
|
||||
// db_instance: db_events,
|
||||
// table_name: 'event',
|
||||
// obj_li: processed_obj_li,
|
||||
// properties_to_save: properties_to_save,
|
||||
// log_lvl: log_lvl
|
||||
// });
|
||||
// }
|
||||
|
||||
// Client-side Filter Layer
|
||||
const filtered_obj_li = processed_obj_li.filter((ev: any) => {
|
||||
// Handle conference filter
|
||||
if (qry_conference != null) {
|
||||
const ev_conf = ev.conference === true || ev.conference === 1 || ev.conference === '1';
|
||||
if (ev_conf !== !!qry_conference) return false;
|
||||
}
|
||||
// // Client-side Filter Layer
|
||||
// const filtered_obj_li = processed_obj_li.filter((ev: any) => {
|
||||
// // Handle conference filter
|
||||
// if (qry_conference != null) {
|
||||
// const ev_conf = ev.conference === true || ev.conference === 1 || ev.conference === '1';
|
||||
// if (ev_conf !== !!qry_conference) return false;
|
||||
// }
|
||||
|
||||
// Location Filtering (Inclusive OR logic)
|
||||
// If either filter is explicitly true, we restrict results.
|
||||
// If both are false or null, we show everything.
|
||||
if (qry_physical === true || qry_virtual === true) {
|
||||
const ev_physical = ev.physical === true || ev.physical === 1 || ev.physical === '1';
|
||||
const ev_virtual = ev.virtual === true || ev.virtual === 1 || ev.virtual === '1';
|
||||
// // Location Filtering (Inclusive OR logic)
|
||||
// // If either filter is explicitly true, we restrict results.
|
||||
// // If both are false or null, we show everything.
|
||||
// if (qry_physical === true || qry_virtual === true) {
|
||||
// const ev_physical = ev.physical === true || ev.physical === 1 || ev.physical === '1';
|
||||
// const ev_virtual = ev.virtual === true || ev.virtual === 1 || ev.virtual === '1';
|
||||
|
||||
let match = false;
|
||||
if (qry_physical === true && ev_physical) match = true;
|
||||
if (qry_virtual === true && ev_virtual) match = true;
|
||||
// let match = false;
|
||||
// if (qry_physical === true && ev_physical) match = true;
|
||||
// if (qry_virtual === true && ev_virtual) match = true;
|
||||
|
||||
if (!match) return false;
|
||||
}
|
||||
// if (!match) return false;
|
||||
// }
|
||||
|
||||
// Handle type filter (skip if null, undefined, 'all', or empty string)
|
||||
if (qry_type != null && qry_type !== 'all' && qry_type !== '') {
|
||||
if (ev.type !== qry_type) return false;
|
||||
}
|
||||
// // Handle type filter (skip if null, undefined, 'all', or empty string)
|
||||
// if (qry_type != null && qry_type !== 'all' && qry_type !== '') {
|
||||
// if (ev.type !== qry_type) return false;
|
||||
// }
|
||||
|
||||
// Handle person ID filter
|
||||
if (qry_person_id) {
|
||||
const match = (
|
||||
ev.external_person_id === qry_person_id ||
|
||||
ev.poc_person_id === qry_person_id ||
|
||||
ev.poc_person_id_random === qry_person_id ||
|
||||
ev.poc_event_person_id === qry_person_id ||
|
||||
ev.poc_event_person_id_random === qry_person_id
|
||||
);
|
||||
if (!match) return false;
|
||||
}
|
||||
// // Handle person ID filter
|
||||
// if (qry_person_id) {
|
||||
// const match = (
|
||||
// ev.external_person_id === qry_person_id ||
|
||||
// ev.poc_person_id === qry_person_id ||
|
||||
// ev.poc_person_id_random === qry_person_id ||
|
||||
// ev.poc_event_person_id === qry_person_id ||
|
||||
// ev.poc_event_person_id_random === qry_person_id
|
||||
// );
|
||||
// if (!match) return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
});
|
||||
// return true;
|
||||
// });
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Filter results (V2): Input=${processed_obj_li.length}, Output=${filtered_obj_li.length}`);
|
||||
}
|
||||
// if (log_lvl) {
|
||||
// console.log(`Filter results (V2): Input=${processed_obj_li.length}, Output=${filtered_obj_li.length}`);
|
||||
// }
|
||||
|
||||
return filtered_obj_li.slice(0, limit);
|
||||
}
|
||||
// return filtered_obj_li.slice(0, limit);
|
||||
// }
|
||||
|
||||
// Updated 2026-03-10
|
||||
export const properties_to_save = [
|
||||
|
||||
@@ -41,7 +41,7 @@ const export_obj = {
|
||||
load_ae_obj_li__event: event.load_ae_obj_li__event,
|
||||
qry_ae_obj_li__event: event.qry_ae_obj_li__event,
|
||||
search__event: event.search__event,
|
||||
qry_ae_obj_li__event_v2: event.qry_ae_obj_li__event_v2,
|
||||
// qry_ae_obj_li__event_v2: event.qry_ae_obj_li__event_v2,
|
||||
create_ae_obj__event: event.create_ae_obj__event,
|
||||
delete_ae_obj_id__event: event.delete_ae_obj_id__event,
|
||||
update_ae_obj__event: event.update_ae_obj__event,
|
||||
|
||||
@@ -10,16 +10,14 @@ import { patch_object } from '$lib/ae_api/api_patch_object'; // Exported at the
|
||||
import { post_object } from '$lib/ae_api/api_post_object'; // Exported at the end of this file
|
||||
|
||||
import { get_ae_obj_id_crud } from '$lib/ae_api/api_get__crud_obj_id';
|
||||
import { get_ae_obj_li_for_obj_id_crud } from '$lib/ae_api/api_get__crud_obj_li_v1';
|
||||
import { get_ae_obj_li_for_obj_id_crud_v2 } from '$lib/ae_api/api_get__crud_obj_li_v2';
|
||||
import { get_ae_lookup_li_v3 } from '$lib/ae_api/api_get__lookup_v3';
|
||||
import { get_ae_lookup_li_v3 } from '$lib/ae_api/api_get__lookup';
|
||||
import {
|
||||
get_ae_obj_v3,
|
||||
get_nested_ae_obj_v3,
|
||||
get_ae_obj_li_v3,
|
||||
get_nested_obj_li_v3
|
||||
} from '$lib/ae_api/api_get__crud_obj_li_v3';
|
||||
import { search_ae_obj_v3 } from '$lib/ae_api/api_post__crud_search_v3';
|
||||
} from '$lib/ae_api/api_get__crud_obj_li';
|
||||
import { search_ae_obj_v3 } from '$lib/ae_api/api_post__crud_search';
|
||||
import {
|
||||
create_ae_obj_v3,
|
||||
create_nested_obj_v3,
|
||||
@@ -29,12 +27,12 @@ import {
|
||||
delete_nested_ae_obj_v3
|
||||
} from '$lib/ae_api/api_post__crud_obj_v3';
|
||||
|
||||
import { get_data_store_v3 } from '$lib/ae_api/api_get__data_store_v3';
|
||||
import { get_data_store_v3 } from '$lib/ae_api/api_get__data_store';
|
||||
|
||||
/**
|
||||
* Get a list of lookup objects (V3 with V2 Fallback)
|
||||
* Get a list of lookup objects (V3)
|
||||
* Standardized lookup data like countries, timezones, and subdivisions.
|
||||
* Updated 2026-02-20
|
||||
* Updated 2026-03-24
|
||||
*/
|
||||
export const get_ae_obj_li_for_lu = async function get_ae_obj_li_for_lu({
|
||||
api_cfg,
|
||||
@@ -72,7 +70,7 @@ export const get_ae_obj_li_for_lu = async function get_ae_obj_li_for_lu({
|
||||
// which leaks account-scoped lookup overrides to all callers.
|
||||
const merged_headers = { ...headers };
|
||||
|
||||
// Use V3 system for primary lookup types
|
||||
// More lists will be added in the future. For now, just country, subdivision, and time_zone.
|
||||
if (['country', 'country_subdivision', 'time_zone'].includes(for_lu_type)) {
|
||||
return await get_ae_lookup_li_v3({
|
||||
api_cfg,
|
||||
@@ -87,22 +85,6 @@ export const get_ae_obj_li_for_lu = async function get_ae_obj_li_for_lu({
|
||||
log_lvl
|
||||
});
|
||||
}
|
||||
|
||||
// Delegate to V2 helper for any other legacy lookup types
|
||||
return await get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg,
|
||||
obj_type: 'lu',
|
||||
for_obj_type: for_lu_type,
|
||||
enabled,
|
||||
hidden,
|
||||
order_by_li,
|
||||
limit,
|
||||
offset,
|
||||
headers: merged_headers,
|
||||
params_json,
|
||||
params,
|
||||
log_lvl
|
||||
});
|
||||
};
|
||||
|
||||
// Updated 2023-07-24
|
||||
@@ -674,8 +656,6 @@ const obj = {
|
||||
get_ae_obj_id_crud: get_ae_obj_id_crud,
|
||||
get_ae_obj_v3: get_ae_obj_v3,
|
||||
get_nested_ae_obj_v3: get_nested_ae_obj_v3,
|
||||
get_ae_obj_li_for_obj_id_crud: get_ae_obj_li_for_obj_id_crud,
|
||||
get_ae_obj_li_for_obj_id_crud_v2: get_ae_obj_li_for_obj_id_crud_v2,
|
||||
get_ae_obj_li_v3: get_ae_obj_li_v3,
|
||||
get_nested_obj_li_v3: get_nested_obj_li_v3,
|
||||
search_ae_obj_v3: search_ae_obj_v3,
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
<script lang="ts">
|
||||
// WARNING: This is deprecated. Do not use!
|
||||
|
||||
import { run } from 'svelte/legacy';
|
||||
|
||||
// This will be the wrapper for the CodeMirror editor. It should hide most of the configuration requirements.
|
||||
// WARNING: This has not been fully updated to Svelte version 5. It is a work in progress.
|
||||
// *** Import Svelte version 5 specific
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { ensureCodeMirrorModules } from '../elements/codemirror_modules';
|
||||
|
||||
interface Props {
|
||||
// Props
|
||||
content?: string;
|
||||
new_content?: string;
|
||||
editorView?: any; // Added to interface
|
||||
// export let language: Extension = markdown(); // javascript()
|
||||
theme_mode?: string; // 'dark' | 'light'
|
||||
extensions?: any[]; // Changed to any[] because Extension type is not directly available here
|
||||
editable?: boolean;
|
||||
readonly?: boolean;
|
||||
placeholder?: string;
|
||||
show_line_numbers?: boolean;
|
||||
wrap_lines?: boolean;
|
||||
use_tab?: boolean;
|
||||
tab_size?: number;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
content = 'test test test test',
|
||||
new_content = $bindable(),
|
||||
editorView = $bindable(), // Exposed for external control
|
||||
theme_mode = $bindable('light'),
|
||||
extensions = [],
|
||||
editable = true,
|
||||
readonly = false,
|
||||
placeholder = 'Start typing...',
|
||||
show_line_numbers = false,
|
||||
wrap_lines = true,
|
||||
use_tab = true,
|
||||
tab_size = 4,
|
||||
class: classes = ''
|
||||
}: Props = $props();
|
||||
|
||||
let editor_element: HTMLDivElement | undefined = $state();
|
||||
// let editorView: any = $state(); // Removed redundant declaration
|
||||
let cm_modules: any = $state(); // To hold the dynamically loaded CodeMirror modules
|
||||
let editor_extensions: any[] = $state([]);
|
||||
|
||||
async function initializeCodeMirror() {
|
||||
if (!browser) return;
|
||||
|
||||
cm_modules = await ensureCodeMirrorModules();
|
||||
if (!cm_modules) return;
|
||||
|
||||
// Reactive declaration for extensions
|
||||
editor_extensions = [
|
||||
// Core extensions
|
||||
cm_modules.highlightSpecialChars(),
|
||||
cm_modules.history(),
|
||||
cm_modules.foldGutter(),
|
||||
cm_modules.drawSelection(),
|
||||
cm_modules.dropCursor(),
|
||||
cm_modules.EditorState_allowMultipleSelections.of(true),
|
||||
cm_modules.indentOnInput(),
|
||||
cm_modules.bracketMatching(),
|
||||
cm_modules.closeBrackets(),
|
||||
cm_modules.autocompletion(),
|
||||
cm_modules.rectangularSelection(),
|
||||
cm_modules.crosshairCursor(),
|
||||
cm_modules.highlightActiveLine(),
|
||||
cm_modules.highlightActiveLineGutter(),
|
||||
cm_modules.keymap.of([
|
||||
...cm_modules.defaultKeymap,
|
||||
...cm_modules.searchKeymap,
|
||||
...cm_modules.historyKeymap,
|
||||
...cm_modules.foldKeymap,
|
||||
...cm_modules.completionKeymap,
|
||||
...cm_modules.lintKeymap
|
||||
]),
|
||||
cm_modules.markdown({
|
||||
base: cm_modules.markdownLanguage,
|
||||
codeLanguages: cm_modules.languages
|
||||
}),
|
||||
theme_mode == 'dark' ? cm_modules.oneDark : cm_modules.EditorView.baseTheme(),
|
||||
cm_modules.EditorView.contentAttributes.of({ spellcheck: 'true' }), // Enable spell check
|
||||
|
||||
// Sync document changes back to Svelte
|
||||
cm_modules.EditorView.updateListener.of((update: any) => {
|
||||
if (update.docChanged) {
|
||||
new_content = update.state.doc.toString();
|
||||
}
|
||||
}),
|
||||
|
||||
// Conditional extensions based on props
|
||||
editable ? cm_modules.EditorView.editable.of(true) : null,
|
||||
readonly ? cm_modules.EditorState.readOnly.of(true) : null,
|
||||
placeholder ? cm_modules.placeholderExt(placeholder) : null,
|
||||
show_line_numbers ? cm_modules.lineNumbers() : null,
|
||||
wrap_lines ? cm_modules.EditorView_lineWrapping : null,
|
||||
use_tab ? cm_modules.keymap.of([cm_modules.indentWithTab]) : null,
|
||||
tab_size ? cm_modules.indentUnit.of(' '.repeat(tab_size)) : null,
|
||||
|
||||
...extensions // Add any custom extensions passed in props
|
||||
].filter(Boolean);
|
||||
|
||||
if (!editor_element) {
|
||||
console.error('Editor element not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
editorView = new cm_modules.EditorView({
|
||||
state: cm_modules.EditorState.create({
|
||||
doc: content,
|
||||
extensions: editor_extensions
|
||||
}),
|
||||
parent: editor_element as HTMLElement
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize CodeMirror on mount
|
||||
onMount(async () => {
|
||||
await initializeCodeMirror();
|
||||
});
|
||||
|
||||
// Clean up on destroy
|
||||
onDestroy(() => {
|
||||
editorView?.destroy();
|
||||
});
|
||||
|
||||
// Update editor content when `content` prop changes
|
||||
$effect(() => {
|
||||
if (editorView && content !== editorView.state.doc.toString()) {
|
||||
editorView.dispatch({
|
||||
changes: { from: 0, to: editorView.state.doc.length, insert: content || '' }
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if browser}
|
||||
<!-- flex flex-col flex-wrap items-center justify-center -->
|
||||
<div
|
||||
bind:this={editor_element}
|
||||
class="codemirror-wrapper h-100 max-h-full w-100 max-w-6xl {classes}"
|
||||
></div>
|
||||
{:else}
|
||||
<div class="scm-waiting {classes}">
|
||||
<div class="scm-waiting__loading scm-loading">
|
||||
<p class="scm-loading__text">Loading editor...</p>
|
||||
</div>
|
||||
|
||||
<pre class="scm-pre cm-editor">{content}</pre>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
/* .codemirror-wrapper :global(.cm-focused) {
|
||||
outline: none;
|
||||
} */
|
||||
|
||||
.codemirror-wrapper {
|
||||
flex-grow: 1;
|
||||
/* flex-shrink: 1; */
|
||||
/* flex-basis: 100%; */
|
||||
|
||||
/* font-size: 1rem; */
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
/* overflow: auto; */
|
||||
/* background-color: var(--cm-background); */
|
||||
|
||||
text-wrap: wrap;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.codemirror-wrapper :global(.cm-editor) {
|
||||
/* font-size: .8rem; */
|
||||
text-wrap: wrap;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
/* max-width: 100%; */
|
||||
/* max-height: 100%; */
|
||||
|
||||
/* overflow: auto; */
|
||||
|
||||
/* width: 100%; */
|
||||
/* height: 100%; */
|
||||
|
||||
/* background-color: var(--cm-background); */
|
||||
/* color: var(--cm-text); */
|
||||
}
|
||||
|
||||
/* .codemirror-wrapper :global(.cm-gutters) {
|
||||
background-color: var(--cm-gutter-background);
|
||||
color: var(--cm-gutter-text);
|
||||
}
|
||||
.codemirror-wrapper :global(.cm-gutter) {
|
||||
background-color: var(--cm-gutter-background);
|
||||
color: var(--cm-gutter-text);
|
||||
}
|
||||
.codemirror-wrapper :global(.cm-gutterElement) {
|
||||
background-color: var(--cm-gutter-background);
|
||||
color: var(--cm-gutter-text);
|
||||
} */
|
||||
</style>
|
||||
@@ -85,7 +85,7 @@ type CMCache = {
|
||||
|
||||
const GLOBAL_KEY = '__cm_singleton_modules_v1';
|
||||
|
||||
export async function ensureCodeMirrorModules(): Promise<CMCache> {
|
||||
export async function ensure_CodeMirror_modules(): Promise<CMCache> {
|
||||
if (!browser) return null;
|
||||
|
||||
// Use a single global object so HMR/multiple module copies reuse same instance
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
*/
|
||||
import { onMount, onDestroy, untrack } from 'svelte';
|
||||
import { browser } from '$app/environment';
|
||||
import { ensureCodeMirrorModules } from './codemirror_modules';
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { ensure_CodeMirror_modules } from './codemirror_modules';
|
||||
// import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
// Icons (Standardized to Lucide where possible, or FontAwesome placeholders)
|
||||
import { Bold, Code, Italic, List, Maximize2 } from '@lucide/svelte';
|
||||
import { Bold, Code, Italic, List, } from '@lucide/svelte';
|
||||
interface Props {
|
||||
content?: string;
|
||||
new_content?: string;
|
||||
@@ -46,7 +46,7 @@
|
||||
async function create_editor() {
|
||||
if (!browser) return;
|
||||
|
||||
cm = await ensureCodeMirrorModules();
|
||||
cm = await ensure_CodeMirror_modules();
|
||||
if (!cm) return;
|
||||
|
||||
// Cleanup existing instance if HMR or remount occurs
|
||||
|
||||
@@ -14,25 +14,25 @@ string_snippets['classes__core_menu'] =
|
||||
|
||||
string_snippets['classes__core_menu__button'] =
|
||||
'btn btn-sm mx-1 preset-tonal-tertiary text-info-300 hover:text-info-800';
|
||||
string_snippets['classes__core_menu__button_highlight'] =
|
||||
'btn btn-sm mx-1 preset-filled-tertiary-500 text-info-300 hover:text-info-800';
|
||||
string_snippets['classes__core_menu__button_warning'] =
|
||||
'btn btn-sm mx-1 preset-tonal-warning text-info-300 hover:text-info-800';
|
||||
// string_snippets['classes__core_menu__button_highlight'] =
|
||||
// 'btn btn-sm mx-1 preset-filled-tertiary-500 text-info-300 hover:text-info-800';
|
||||
// string_snippets['classes__core_menu__button_warning'] =
|
||||
// 'btn btn-sm mx-1 preset-tonal-warning text-info-300 hover:text-info-800';
|
||||
|
||||
// string_snippets['classes__events_pres_mgmt_menu'] = 'flex flex-col items-center space-y-1 border border-blue-200 rounded-md py-1 px-2 hover:bg-blue-100 transition-all duration-700 hover:duration-300';
|
||||
string_snippets['classes__events_pres_mgmt_menu'] =
|
||||
'w-full flex flex-col items-center gap-1 border border-gray-200 rounded-md p-1 hover:bg-gray-100 transition-all duration-700 hover:duration-300';
|
||||
// string_snippets['classes__events_pres_mgmt_menu'] =
|
||||
// 'w-full flex flex-col items-center gap-1 border border-gray-200 rounded-md p-1 hover:bg-gray-100 transition-all duration-700 hover:duration-300';
|
||||
|
||||
string_snippets['classes__events_pres_mgmt_menu__button'] =
|
||||
'btn btn-sm mx-1 preset-tonal-secondary hover:preset-filled-secondary-500';
|
||||
string_snippets['classes__events_pres_mgmt_menu__button_special'] =
|
||||
'btn btn-sm mx-1 hover:preset-filled-primary-500';
|
||||
// string_snippets['classes__events_pres_mgmt_menu__button'] =
|
||||
// 'btn btn-sm mx-1 preset-tonal-secondary hover:preset-filled-secondary-500';
|
||||
// string_snippets['classes__events_pres_mgmt_menu__button_special'] =
|
||||
// 'btn btn-sm mx-1 hover:preset-filled-primary-500';
|
||||
|
||||
string_snippets['classes__events_pres_mgmt_menu__button_highlight'] =
|
||||
'btn btn-sm mx-1 preset-filled-tertiary-500 text-info-300 hover:text-info-800';
|
||||
string_snippets['classes__events_pres_mgmt_menu__button_warning'] =
|
||||
'btn btn-sm mx-1 preset-tonal-warning text-info-300 hover:text-info-800';
|
||||
string_snippets['classes__events_pres_mgmt_menu__button_warning_special'] =
|
||||
'btn btn-sm mx-1 preset-tonal-warning';
|
||||
// string_snippets['classes__events_pres_mgmt_menu__button_highlight'] =
|
||||
// 'btn btn-sm mx-1 preset-filled-tertiary-500 text-info-300 hover:text-info-800';
|
||||
// string_snippets['classes__events_pres_mgmt_menu__button_warning'] =
|
||||
// 'btn btn-sm mx-1 preset-tonal-warning text-info-300 hover:text-info-800';
|
||||
// string_snippets['classes__events_pres_mgmt_menu__button_warning_special'] =
|
||||
// 'btn btn-sm mx-1 preset-tonal-warning';
|
||||
|
||||
// export string_snippets;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
// place files you want to import through the `$lib` alias in this folder.
|
||||
@@ -411,8 +411,6 @@
|
||||
person={$lq__person_obj}
|
||||
onSave={(updated) => {
|
||||
is_editing = false;
|
||||
// The liveQuery should pick up the changes after they are saved to IndexedDB
|
||||
// inside update_ae_obj__person -> db_save_ae_obj_li__ae_obj
|
||||
}}
|
||||
onCancel={() => is_editing = false}
|
||||
/>
|
||||
@@ -420,12 +418,5 @@
|
||||
{:else}
|
||||
<Person_view person_id={$slct.person_id} />
|
||||
{/if}
|
||||
<!-- {:catch error}
|
||||
<div class="text-red-800">
|
||||
<span class="fas fa-exclamation-triangle text-xl"></span>
|
||||
<span>Error: {error.message}</span>
|
||||
</div>
|
||||
{/await} -->
|
||||
|
||||
<!-- {$slct.person_id ?? 'Unknown ID'} -->
|
||||
</section>
|
||||
|
||||
@@ -17,13 +17,11 @@
|
||||
console.log(`ae_events_pres_mgmt presenter_view.svelte`);
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
// import { liveQuery } from "dexie";
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import { api } from '$lib/api/api';
|
||||
import Element_ae_obj_field_editor_v3 from '$lib/elements/element_ae_obj_field_editor_v3.svelte';
|
||||
// import Element_data_store from '$lib/element_data_store.svelte';
|
||||
import MyClipboard from '$lib/app_components/e_app_clipboard.svelte';
|
||||
|
||||
import { core_func } from '$lib/ae_core/ae_core_functions';
|
||||
@@ -53,14 +51,7 @@
|
||||
let ae_promises: { [key: string]: any } = $state({});
|
||||
let ae_tmp: { [key: string]: any } = $state({ show__file_li: true });
|
||||
|
||||
// console.log(`event_presenter_id:`, $lq__event_presenter_obj?.event_presenter_id);
|
||||
|
||||
// console.log(`event_presentation_id:`, $lq__event_presentation_obj?.event_presentation_id);
|
||||
|
||||
// ae_tmp.biography = '';
|
||||
ae_tmp.biography = null;
|
||||
// ae_tmp.biography = $lq__event_presenter_obj?.biography ?? '';
|
||||
// console.log(`ae_tmp.biography:`, ae_tmp.biography);
|
||||
|
||||
$effect(() => {
|
||||
if (
|
||||
@@ -993,8 +984,6 @@
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (update_result: any) {
|
||||
// console.log(update_result);
|
||||
// return update_result;
|
||||
});
|
||||
}}
|
||||
class:hidden={!ae_tmp.biography ||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { PUBLIC_AE_BOOTSTRAP_KEY } from '$env/static/public';
|
||||
|
||||
import { api } from '$lib/api/api';
|
||||
// import { api } from '$lib/api/api';
|
||||
import { ae_loc, ae_api, ae_sess } from '$lib/stores/ae_stores';
|
||||
import { get_object } from '$lib/ae_api/api_get_object';
|
||||
// import { get_object } from '$lib/ae_api/api_get_object';
|
||||
import { post_object } from '$lib/ae_api/api_post_object';
|
||||
import { patch_object } from '$lib/ae_api/api_patch_object';
|
||||
import { ArrowRightLeft, Bug, Building2, CircleCheck, Code, Contact, Database, Eye, EyeOff, FlaskConical, Globe, Info, Key, MapPin, RefreshCcw, Satellite, Server, Settings2, ShieldAlert, ShieldCheck, Trash2, Unlock, User, UserCheck, Users, Zap } from '@lucide/svelte';
|
||||
|
||||
Reference in New Issue
Block a user