diff --git a/migration/r4.4/analytics.sql b/migration/r4.4/analytics.sql new file mode 100644 index 00000000..f9625899 --- /dev/null +++ b/migration/r4.4/analytics.sql @@ -0,0 +1,20 @@ +create table useranalytics ( +id serial not null primary key, +userid int not null, +year int not null, +month int not null +); +create unique index ux_useranalytics on useranalytics(userid, year, month); +grant all on useranalytics to transcriber; +grant all on useranalytics_id_seq to transcriber; + + +create table countryanalytics ( +id serial not null primary key, +country text not null, +year int not null, +month int not null +); +create unique index ux_countryanalytics on countryanalytics(country, year, month); +grant all on countryanalytics to transcriber; +grant all on countryanalytics_id_seq to transcriber; diff --git a/src/renderer/src/Sources.tsx b/src/renderer/src/Sources.tsx index fa85dac3..3e3df68d 100644 --- a/src/renderer/src/Sources.tsx +++ b/src/renderer/src/Sources.tsx @@ -42,6 +42,7 @@ import { updateBackTranslationType } from './crud/updateBackTranslationType'; import { updateConsultantWorkflowStep } from './crud/updateConsultantWorkflowStep'; import { serializersSettings } from './serializers/serializersFor'; import { requestedSchema } from './schema'; +import { logLoginAnalytics } from './crud/logLoginAnalytics'; import { orbitReset } from './crud/orbitReset'; type StategyError = (...args: unknown[]) => unknown; @@ -442,6 +443,7 @@ export const Sources = async ( await forceDataChanges(); console.log(`Forcing complete`); } + logLoginAnalytics(tokenState.accessToken, errorReporter); } const user = localStorage.getItem(LocalKey.userId) as string; setUser(user); diff --git a/src/renderer/src/crud/index.ts b/src/renderer/src/crud/index.ts index 6a37ed38..d67bcb59 100644 --- a/src/renderer/src/crud/index.ts +++ b/src/renderer/src/crud/index.ts @@ -6,6 +6,7 @@ export * from './getOrgs'; export * from './groupmembership'; export * from './hasAnyRelated'; export * from './loadData'; +export * from './logLoginAnalytics'; export * from './media'; export * from './offlineError'; export * from './passage'; diff --git a/src/renderer/src/crud/logLoginAnalytics.ts b/src/renderer/src/crud/logLoginAnalytics.ts new file mode 100644 index 00000000..2879d71a --- /dev/null +++ b/src/renderer/src/crud/logLoginAnalytics.ts @@ -0,0 +1,19 @@ +import Bugsnag from '@bugsnag/js'; +import { axiosPost } from '../utils/axios'; +import { infoMsg, logError, Severity } from '../utils'; + +export async function logLoginAnalytics( + token?: string | null, + errorReporter?: typeof Bugsnag +): Promise { + if (!token) return; + try { + await axiosPost('useranalytics/track', undefined, token); + } catch (error) { + logError( + Severity.error, + errorReporter, + infoMsg(error as Error, 'logLoginAnalytics failed') + ); + } +} diff --git a/src/renderer/src/model/countryAnalytics.tsx b/src/renderer/src/model/countryAnalytics.tsx new file mode 100644 index 00000000..da845c05 --- /dev/null +++ b/src/renderer/src/model/countryAnalytics.tsx @@ -0,0 +1,13 @@ +import { InitializedRecord, UninitializedRecord } from '@orbit/records'; + +export interface CountryAnalytics extends UninitializedRecord { + attributes: { + country: string; + year: number; + month: number; + }; +} + +export type CountryAnalyticsD = CountryAnalytics & InitializedRecord; + +export default CountryAnalytics; diff --git a/src/renderer/src/model/index.tsx b/src/renderer/src/model/index.tsx index 937f2e68..f1a1f993 100644 --- a/src/renderer/src/model/index.tsx +++ b/src/renderer/src/model/index.tsx @@ -68,5 +68,7 @@ export * from './organizationBible'; export * from './paratextProject'; export * from './intellectualProperty'; export * from './vwchecksum'; +export * from './userAnalytics'; +export * from './countryAnalytics'; export * from './IExecResult'; export * from './SectionArray'; diff --git a/src/renderer/src/model/userAnalytics.tsx b/src/renderer/src/model/userAnalytics.tsx new file mode 100644 index 00000000..fd840c49 --- /dev/null +++ b/src/renderer/src/model/userAnalytics.tsx @@ -0,0 +1,13 @@ +import { InitializedRecord, UninitializedRecord } from '@orbit/records'; + +export interface UserAnalytics extends UninitializedRecord { + attributes: { + userId: number; + year: number; + month: number; + }; +} + +export type UserAnalyticsD = UserAnalytics & InitializedRecord; + +export default UserAnalytics; diff --git a/src/renderer/src/schema.tsx b/src/renderer/src/schema.tsx index f8e617ef..c4673967 100644 --- a/src/renderer/src/schema.tsx +++ b/src/renderer/src/schema.tsx @@ -1035,6 +1035,25 @@ if (requestedSchema > 9 && schemaDefinition.models) { }; schemaDefinition.version = 10; } +if (requestedSchema > 10 && schemaDefinition.models) { + schemaDefinition.models.useranalytics = { + keys: { remoteId: {} }, + attributes: { + userId: { type: 'number' }, + year: { type: 'number' }, + month: { type: 'number' }, + }, + }; + schemaDefinition.models.countryanalytics = { + keys: { remoteId: {} }, + attributes: { + country: { type: 'string' }, + year: { type: 'number' }, + month: { type: 'number' }, + }, + }; + schemaDefinition.version = 11; +} export const schema = new RecordSchema(schemaDefinition);