Standardize Core UI forms and unify schemas for V3 API compatibility

- Implement new Svelte 5 Person, Address, and Contact form components with surgical payload logic.
- Refactor core routes (People, Addresses, Contacts) to support unified Create/Edit workflows.
- Update ae_types.ts, db_core.ts, and db_journals.ts to align with V3 backend object models.
- Fix type safety issues in Journal history views and refine metadata display.
- Migrate person core functions to the newer ae_core__person module.
This commit is contained in:
Scott Idem
2026-01-09 15:14:36 -05:00
parent 8e205b2db9
commit 5056d5d8f0
18 changed files with 1276 additions and 944 deletions

View File

@@ -17,7 +17,7 @@ import {
delete_ae_obj_id__person,
update_ae_obj__person
// db_save_ae_obj_li__person
} from '$lib/ae_core/core__person';
} from '$lib/ae_core/ae_core__person';
import {
auth_ae_obj__username_password,

View File

@@ -1,208 +1,91 @@
import Dexie, { type Table } from 'dexie';
import type {
ae_HostedFile,
ae_Person,
ae_User,
ae_Account,
ae_Site,
ae_SiteDomain,
ae_Address,
ae_Contact
} from '$lib/types/ae_types';
// li = list
// kv = key value list
// Updated 2025-01-07
export interface File {
id: string;
id_random: string;
hosted_file_id: string;
hosted_file_id_random: string;
hash_sha256: string;
for_type?: string;
for_id?: string;
for_id_random?: string;
account_id: string;
filename: string;
extension: string;
content_type: string;
size: number; // In bytes
enable: null | boolean;
hide?: null | boolean;
priority?: null | boolean;
sort?: null | number;
group?: null | string;
notes?: null | string;
created_on: Date;
updated_on?: null | Date;
// Additional fields for convenience (database views)
filename_no_ext: string;
filename_w_ext: string;
// Updated 2026-01-09 - Unified Types
export interface File extends ae_HostedFile {
// Legacy mapping support
content_type?: string;
filename_no_ext?: string;
filename_w_ext?: string;
}
// Updated 2024-07-17
export interface Person {
id: string;
// id_random: string;
person_id: string;
person_id_random: string;
external_id?: string; // This may be semi-random or unique only withing the account.
external_sys_id?: string; // Generated by an external system. Ideally this should be something like a UUID. It may be the same as the external_id if nothing given.
code?: string; // Not currently used.
account_id?: string; // Technically this is not required for global users.
account_id_random?: string; // Technically this is not required for global users.
person_profile_id?: null | string;
person_profile_id_random?: null | string; // The new table person_profile will be used soon...
user_id?: string;
user_id_random?: string;
pronouns?: null | string;
informal_name?: null | string;
title_names?: null | string;
given_name: string;
middle_name?: null | string;
family_name: null | string;
designations?: null | string;
professional_title?: null | string;
full_name?: string;
full_name_override?: null | string; // was called display_name
affiliations?: null | string;
primary_email?: string;
biography?: null | string;
agree?: null | boolean;
comments?: null | string;
allow_auth_key?: null | boolean; // For sign in without password
auth_key?: null | string; // Should this be saved locally?
passcode?: null | string;
data_json?: null | string;
enable: null | boolean;
hide?: null | boolean;
priority?: null | boolean;
sort?: null | number;
group?: null | string;
notes?: null | string;
created_on: Date;
updated_on?: null | Date;
// Generated fields for sorting locally only
tmp_sort_1?: null | string;
tmp_sort_2?: null | string;
tmp_sort_3?: null | string;
// Additional fields for convenience (database views)
username?: string; // Same as user_username
// user_username?: null|string; // Same as username
user_name?: null | string;
user_email?: null | string;
user_allow_auth_key?: null | boolean; // For sign in without password
export interface Person extends ae_Person {
// Legacy mapping support and view fields
external_id?: string;
external_sys_id?: string;
person_profile_id?: string;
person_profile_id_random?: string;
username?: string;
user_name?: string;
user_email?: string;
user_super?: boolean;
user_manager?: boolean;
user_administrator?: boolean;
user_public?: boolean;
organization_id?: null | string; // The organization this person belongs to, if any.
organization_id_random?: null | string; // The random ID of the organization this person belongs to, if any.
organization_name?: null | string;
organization_id?: string;
organization_id_random?: string;
organization_name?: string;
contact_id?: null | string; // The contact ID of the person, if any.
contact_id_random?: null | string; // The random ID of the contact, if any.
contact_name?: null | string;
contact_email?: null | string;
contact_cc_email?: null | string;
contact_phone_mobile?: null | string;
contact_phone_home?: null | string;
contact_phone_office?: null | string;
contact_phone_landline?: null | string;
contact_phone_fax?: null | string;
contact_phone_other?: null | string;
contact_id?: string;
contact_id_random?: string;
contact_name?: string;
address_id?: null | string; // The address ID of the person, if any.
address_id_random?: null | string; // The random ID of the address, if any.
address_city?: null | string;
address_country_alpha_2_code?: null | string; // ISO 3166-1 alpha-2 country code
address_id?: string;
address_id_random?: string;
}
// Updated 2026-01-06
export interface User {
id: string;
user_id: string;
user_id_random: string;
username: string;
name: string;
email: string;
allow_auth_key: boolean;
super: boolean;
manager: boolean;
administrator: boolean;
verified: boolean;
public: boolean;
person_id?: string;
person_id_random?: string;
enable: null | boolean;
hide?: null | boolean;
priority?: null | boolean;
sort?: null | number;
group?: null | string;
notes?: null | string;
created_on: Date;
updated_on?: null | Date;
tmp_sort_1?: string;
tmp_sort_2?: string;
export interface User extends ae_User {
// Additional local fields if needed
}
// Updated 2026-01-06
// Updated 2026-01-09
export class MySubClassedDexie extends Dexie {
file!: Table<File>;
person!: Table<Person>;
user!: Table<User>;
account!: Table<any>;
site!: Table<any>;
site_domain!: Table<any>;
address!: Table<any>;
contact!: Table<any>;
account!: Table<ae_Account>;
site!: Table<ae_Site>;
site_domain!: Table<ae_SiteDomain>;
address!: Table<ae_Address>;
contact!: Table<ae_Contact>;
constructor() {
super('ae_core_db');
this.version(1).stores({
this.version(2).stores({
file: `
id, id_random, hosted_file_id, hosted_file_id_random,
id, hosted_file_id, hosted_file_id_random,
hash_sha256,
account_id,
account_id, account_id_random,
for_type, for_id, for_id_random,
filename, extension,
content_type, size,
enable, hide, priority, sort, group, created_on, updated_on`,
person: `
id, person_id, person_id_random,
external_id, code,
account_id, user_id,
account_id_random, user_id_random,
person_profile_id,
person_profile_id_random,
account_id, account_id_random,
user_id, user_id_random,
given_name, family_name,
full_name, affiliations, email,
agree,
enable, hide, priority, sort, group, created_on, updated_on`,
user: `
id, user_id, user_id_random,
username, name, email,
username, email,
super, manager, administrator,
enable, hide, priority, sort, group, created_on, updated_on`,
@@ -220,21 +103,21 @@ export class MySubClassedDexie extends Dexie {
site_domain: `
id, site_domain_id, site_domain_id_random,
site_id, site_id_random,
domain,
fqdn,
enable, hide, priority, sort, group, created_on, updated_on`,
address: `
id, address_id, address_id_random,
account_id, account_id_random,
for_type, for_id, for_id_random,
for_type, for_id_random,
city, state_province, country,
enable, hide, priority, sort, group, created_on, updated_on`,
contact: `
id, contact_id, contact_id_random,
account_id, account_id_random,
for_type, for_id, for_id_random,
name, email, phone,
for_type, for_id_random,
title, email, phone_mobile,
enable, hide, priority, sort, group, created_on, updated_on`
});
}