Skip to content

Commit 5540ef4

Browse files
committed
feat: user import action
1 parent 811416e commit 5540ef4

File tree

2 files changed

+69
-7
lines changed

2 files changed

+69
-7
lines changed

src/app/shared/components/template/services/template-field.service.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,31 @@ import { booleanStringToBoolean } from "src/app/shared/utils";
77
import { TemplateTranslateService } from "./template-translate.service";
88
import { AsyncServiceBase } from "src/app/shared/services/asyncService.base";
99
import { TemplateActionRegistry } from "./instance/template-action.registry";
10+
import { AppConfigService } from "src/app/shared/services/app-config/app-config.service";
1011

1112
@Injectable({ providedIn: "root" })
1213
export class TemplateFieldService extends AsyncServiceBase {
1314
globals: { [name: string]: FlowTypes.GlobalRow } = {};
1415

16+
/** App config prefix used */
17+
public prefix: string;
18+
1519
constructor(
1620
private localStorageService: LocalStorageService,
1721
private dbService: DbService,
1822
private translateService: TemplateTranslateService,
19-
private templateActionRegistry: TemplateActionRegistry
23+
private templateActionRegistry: TemplateActionRegistry,
24+
private appConfigService: AppConfigService
2025
) {
2126
super("TemplateField");
2227
this.registerInitFunction(this.initialise);
2328
this.registerTemplateActionHandlers();
29+
this.prefix = appConfigService.APP_CONFIG.FIELD_PREFIX;
2430
}
2531

2632
private async initialise() {
2733
await this.ensureAsyncServicesReady([this.dbService, this.translateService]);
28-
this.ensureSyncServicesReady([this.localStorageService]);
34+
this.ensureSyncServicesReady([this.localStorageService, this.appConfigService]);
2935
}
3036

3137
private registerTemplateActionHandlers() {
@@ -49,7 +55,7 @@ export class TemplateFieldService extends AsyncServiceBase {
4955
* TODO - ideally showWarnings should be linked to some sort of debug mode
5056
*/
5157
public getField(key: string, showWarnings = true) {
52-
let val: any = this.localStorageService.getString("rp-contact-field." + key);
58+
let val: any = this.localStorageService.getString(`${this.prefix}.${key}`);
5359
// provide a fallback if the target variable does not exist in local storage
5460
if (val === null && showWarnings) {
5561
// console.warn("field value not found for key:", key);
@@ -80,7 +86,7 @@ export class TemplateFieldService extends AsyncServiceBase {
8086
}
8187
}
8288
// write to local storage - this will cast to string
83-
this.localStorageService.setString("rp-contact-field." + key, value);
89+
this.localStorageService.setString(`${this.prefix}.${key}`, value);
8490

8591
// write to db - note this can handle more data formats but only string/number will be available to queries
8692
if (typeof value === "boolean") value = "value";

src/app/shared/services/userMeta/userMeta.service.ts

+59-3
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
1+
import { HttpClient } from "@angular/common/http";
12
import { Injectable } from "@angular/core";
23
import { Device } from "@capacitor/device";
4+
import { firstValueFrom } from "rxjs";
5+
36
import { AsyncServiceBase } from "../asyncService.base";
47
import { DbService } from "../db/db.service";
8+
import { TemplateActionRegistry } from "../../components/template/services/instance/template-action.registry";
9+
import { TemplateFieldService } from "../../components/template/services/template-field.service";
510

611
@Injectable({ providedIn: "root" })
712
export class UserMetaService extends AsyncServiceBase {
813
/** keep an in-memory copy of user to provide synchronously */
914
public userMeta: IUserMeta;
10-
constructor(private dbService: DbService) {
11-
super("UsesrMetaService");
15+
constructor(
16+
private dbService: DbService,
17+
private templateActionRegistry: TemplateActionRegistry,
18+
private http: HttpClient,
19+
private fieldService: TemplateFieldService
20+
) {
21+
super("UserMetaService");
1222
this.registerInitFunction(this.initialise);
1323
}
1424

1525
/** When first initialising ensure a default profile created and any newer defaults are merged with older user profiles */
1626
private async initialise() {
17-
await this.ensureAsyncServicesReady([this.dbService]);
27+
await this.ensureAsyncServicesReady([this.dbService, this.fieldService]);
28+
this.registerUserActions();
1829
const userMetaValues = await this.dbService.table<IUserMetaEntry>("user_meta").toArray();
1930
const userMeta: IUserMeta = USER_DEFAULTS;
2031
userMetaValues.forEach((v) => {
@@ -27,6 +38,8 @@ export class UserMetaService extends AsyncServiceBase {
2738
}
2839
userMeta.uuid = uuid;
2940
this.userMeta = userMeta;
41+
// populate user id contact field
42+
this.fieldService.setField("_app_user_id", uuid);
3043
}
3144

3245
getUserMeta(key: keyof IUserMeta) {
@@ -38,6 +51,49 @@ export class UserMetaService extends AsyncServiceBase {
3851
await this.dbService.table<IUserMetaEntry>("user_meta").bulkPut(entries as any);
3952
this.userMeta = { ...this.userMeta, ...meta };
4053
}
54+
55+
/** Import existing user contact fields and replace current user */
56+
private async importUserFields(id: string) {
57+
try {
58+
// TODO - get type-safe return types using openapi http client
59+
const profile = await firstValueFrom(
60+
this.http.get(`/app_users/${id}`, { responseType: "json" })
61+
);
62+
if (!profile) {
63+
console.error("[User Import] not found:" + id);
64+
return;
65+
}
66+
const { contact_fields } = profile as any;
67+
for (const [key, value] of Object.entries(contact_fields)) {
68+
const fieldName = key.replace(`${this.fieldService.prefix}.`, "");
69+
// TODO - handle special contact fields as required (e.g. _app_skin, _app_theme)
70+
if (!fieldName.startsWith("_")) {
71+
await this.fieldService.setField(fieldName, value as string);
72+
}
73+
}
74+
} catch (error) {
75+
console.error("[User Import] failed", error);
76+
}
77+
}
78+
79+
private registerUserActions() {
80+
const childActions = {
81+
import: this.importUserFields.bind(this),
82+
};
83+
const childActionNames = Object.keys(childActions).join(",");
84+
this.templateActionRegistry.register({
85+
user: async ({ args }) => {
86+
const [actionId, ...childArgs] = args;
87+
if (!childActions[actionId]) {
88+
console.error(
89+
`[${actionId}] user action not defined. Available actions:\n${childActionNames}`
90+
);
91+
return;
92+
}
93+
return childActions[actionId](childArgs);
94+
},
95+
});
96+
}
4197
}
4298

4399
interface IUserMetaEntry {

0 commit comments

Comments
 (0)