From 9b7f062b01a911605fe8ebb00e14b0b7f4060a33 Mon Sep 17 00:00:00 2001 From: Johnny McQuade Date: Wed, 11 Sep 2024 11:45:43 +0100 Subject: [PATCH] wip: handle user id change on user import action --- .../services/template-calc.service.ts | 24 +++++++---- .../local-storage/local-storage.service.ts | 5 +++ .../services/userMeta/userMeta.service.ts | 40 ++++++++++++------- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/app/shared/components/template/services/template-calc.service.ts b/src/app/shared/components/template/services/template-calc.service.ts index 42e4ce5b8..d6bd865b7 100644 --- a/src/app/shared/components/template/services/template-calc.service.ts +++ b/src/app/shared/components/template/services/template-calc.service.ts @@ -7,7 +7,6 @@ import { DataEvaluationService } from "src/app/shared/services/data/data-evaluat import { AsyncServiceBase } from "src/app/shared/services/asyncService.base"; import { PLH_CALC_FUNCTIONS } from "./template-calc-functions/plh-calc-functions"; import { CORE_CALC_FUNCTIONS } from "./template-calc-functions/core-calc-functions"; -import { UserMetaService } from "src/app/shared/services/userMeta/userMeta.service"; import { LocalStorageService } from "src/app/shared/services/local-storage/local-storage.service"; @Injectable({ providedIn: "root" }) @@ -25,15 +24,14 @@ export class TemplateCalcService extends AsyncServiceBase { constructor( private serverService: ServerService, private dataEvaluationService: DataEvaluationService, - private localStorageService: LocalStorageService, - private userMetaService: UserMetaService + private localStorageService: LocalStorageService ) { super("TemplateCalc"); this.registerInitFunction(this.initialise); } private async initialise() { this.ensureSyncServicesReady([this.serverService, this.localStorageService]); - await this.ensureAsyncServicesReady([this.dataEvaluationService, this.userMetaService]); + await this.ensureAsyncServicesReady([this.dataEvaluationService]); await this.setUserMetaData(); this.getCalcContext(); } @@ -49,6 +47,10 @@ export class TemplateCalcService extends AsyncServiceBase { return this.calcContext; } + public updateThisCtxt(field: K, value: IThisCtxt[K]) { + this.calcContext.thisCtxt[field] = value; + } + /** * Main export for use in evaluation statements. Includes all functions listed below * alongside additional a base for variables found at `this.` @@ -67,7 +69,7 @@ export class TemplateCalcService extends AsyncServiceBase { app_first_launch: this.dataEvaluationService.data.first_app_launch, app_user_id: this.app_user_id, device_info: this.device_info, - }; + } as IThisCtxt; } private async setUserMetaData() { @@ -119,9 +121,15 @@ export class TemplateCalcService extends AsyncServiceBase { * `pick_random(this.local.some_list)` */ export interface ICalcContext { - thisCtxt: { - [name: string]: any; - }; + thisCtxt: IThisCtxt; globalFunctions: IFunctionHashmap; globalConstants: IConstantHashmap; } + +interface IThisCtxt { + calc: Function; + app_day: number; + app_first_launch: string; + app_user_id: string; + device_info: DeviceInfo; +} diff --git a/src/app/shared/services/local-storage/local-storage.service.ts b/src/app/shared/services/local-storage/local-storage.service.ts index eff7e8764..09b56bd83 100644 --- a/src/app/shared/services/local-storage/local-storage.service.ts +++ b/src/app/shared/services/local-storage/local-storage.service.ts @@ -97,4 +97,9 @@ export class LocalStorageService extends SyncServiceBase { } return key.startsWith("_"); } + /** Check if a field name is protected (starts with underscore prefixed or non-prefixed) */ + getProtectedFieldNameWithPrefix(field: IProtectedFieldName) { + const fieldName = getProtectedFieldName(field); + return `${STORAGE_PREFIX}.${fieldName}`; + } } diff --git a/src/app/shared/services/userMeta/userMeta.service.ts b/src/app/shared/services/userMeta/userMeta.service.ts index 102c6a9c2..f3bf5ad77 100644 --- a/src/app/shared/services/userMeta/userMeta.service.ts +++ b/src/app/shared/services/userMeta/userMeta.service.ts @@ -9,6 +9,7 @@ import { TemplateActionRegistry } from "../../components/template/services/insta import { TemplateFieldService } from "../../components/template/services/template-field.service"; import { LocalStorageService } from "../local-storage/local-storage.service"; import { DynamicDataService } from "../dynamic-data/dynamic-data.service"; +import { TemplateCalcService } from "../../components/template/services/template-calc.service"; type IDynamicDataState = ReturnType; @@ -17,12 +18,13 @@ export class UserMetaService extends AsyncServiceBase { /** keep an in-memory copy of user to provide synchronously */ public userMeta: IUserMeta; constructor( - private localStorageService: LocalStorageService, private dbService: DbService, - private templateActionRegistry: TemplateActionRegistry, - private http: HttpClient, + private dynamicDataService: DynamicDataService, private fieldService: TemplateFieldService, - private dynamicDataService: DynamicDataService + private http: HttpClient, + private localStorageService: LocalStorageService, + private templateActionRegistry: TemplateActionRegistry, + private templateCalcService: TemplateCalcService ) { super("UserMetaService"); this.registerInitFunction(this.initialise); @@ -35,22 +37,16 @@ export class UserMetaService extends AsyncServiceBase { this.dbService, this.fieldService, this.dynamicDataService, + this.templateCalcService, ]); this.registerUserActions(); const userMetaValues = await this.dbService.table("user_meta").toArray(); - const userMeta: IUserMeta = USER_DEFAULTS; + this.userMeta = USER_DEFAULTS; userMetaValues.forEach((v) => { - userMeta[v.key] = v.value; + this.userMeta[v.key] = v.value; }); const { identifier: uuid } = await Device.getId(); - // fix legacy user IDs - note this can likely be removed after v0.16 - if (userMeta.uuid && userMeta.uuid !== uuid) { - await this.setUserMeta({ uuid, uuid_temp: userMeta.uuid }); - } - userMeta.uuid = uuid; - this.userMeta = userMeta; - // populate user id contact field - this.localStorageService.setProtected("APP_USER_ID", uuid); + await this.updateUuid(uuid); } getUserMeta(key: keyof IUserMeta) { @@ -83,12 +79,28 @@ export class UserMetaService extends AsyncServiceBase { } } + private async updateUuid(uuid: string) { + // fix legacy user IDs - note this can likely be removed after v0.16 + if (this.userMeta.uuid && this.userMeta.uuid !== uuid) { + await this.setUserMeta({ uuid, uuid_temp: this.userMeta.uuid }); + } + this.userMeta.uuid = uuid; + // populate user id contact field + this.localStorageService.setProtected("APP_USER_ID", uuid); + // update calc context + this.templateCalcService.updateThisCtxt("app_user_id", uuid); + } + private async importUserContactFields(contact_fields = {}) { for (const [key, value] of Object.entries(contact_fields)) { // TODO - handle special contact fields as required (e.g. _app_skin, _app_theme) if (!this.localStorageService.isProtected(key)) { this.localStorageService.setString(key, value as string); } + // handle user ID import + if (key === this.localStorageService.getProtectedFieldNameWithPrefix("APP_USER_ID")) { + await this.updateUuid(String(value)); + } } }