Skip to content

Commit

Permalink
Merge pull request #1548 from RADAR-base/release-2.6.0-alpha
Browse files Browse the repository at this point in the history
Release 2.6.0-alpha
  • Loading branch information
mpgxvii committed Sep 9, 2022
2 parents 827d58c + 27479a9 commit 5bc3d70
Show file tree
Hide file tree
Showing 26 changed files with 761 additions and 241 deletions.
2 changes: 1 addition & 1 deletion config.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<widget android-versionCode="569" id="org.phidatalab.radar_armt" ios-CFBundleIdentifier="org.phidatalab.radar-armt" ios-CFBundleVersion="1" version="2.5.1" xmlns:android="http://schemas.android.com/apk/res/android">
<widget android-versionCode="570" id="org.phidatalab.radar_armt" ios-CFBundleIdentifier="org.phidatalab.radar-armt" ios-CFBundleVersion="1" version="2.6.0-alpha" xmlns:android="http://schemas.android.com/apk/res/android">
<name>RADAR Questionnaire</name>
<description>An application that collects active data for research.</description>
<author email="radar-base@kcl.ac.uk" href="http://radar-base.org/">RADAR-Base</author>
Expand Down
251 changes: 239 additions & 12 deletions src/app/core/services/app-server/app-server.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { HttpClient, HttpHeaders } from '@angular/common/http'
import {
HttpClient,
HttpErrorResponse,
HttpHeaders,
HttpResponse
} from '@angular/common/http'
import { Injectable } from '@angular/core'
import * as moment from 'moment-timezone'
import * as urljoin from 'url-join'
Expand All @@ -9,19 +14,33 @@ import {
} from '../../../../assets/data/defaultConfig'
import { ConfigKeys } from '../../../shared/enums/config'
import { StorageKeys } from '../../../shared/enums/storage'
import {
FcmNotificationDto,
FcmNotificationError
} from '../../../shared/models/app-server'
import { SingleNotification } from '../../../shared/models/notification-handler'
import { Task } from '../../../shared/models/task'
import { RemoteConfigService } from '../config/remote-config.service'
import { SubjectConfigService } from '../config/subject-config.service'
import { LocalizationService } from '../misc/localization.service'
import { LogService } from '../misc/log.service'
import { StorageService } from '../storage/storage.service'
import { TokenService } from '../token/token.service'
import { filter } from "rxjs/operators";
import { Subscription } from "rxjs";

@Injectable()
export class AppServerService {
private APP_SERVER_URL
SUBJECT_PATH = 'users'
PROJECT_PATH = 'projects'
GITHUB_CONTENT_PATH = 'github/content'
QUESTIONNAIRE_SCHEDULE_PATH = 'questionnaire/schedule'
QUESTIONNAIRE_TASK = 'questionnaire/task'
QUESTIONNAIRE_STATE_EVENTS_PATH = 'state_events'
NOTIFICATIONS_PATH = 'messaging/notifications'
STATE_EVENTS_PATH = 'state_events'
private tokenSubscription: Subscription = null

constructor(
public storage: StorageService,
Expand All @@ -35,7 +54,7 @@ export class AppServerService {

init() {
// NOTE: Initialising ensures project and subject exists in the app server
return Promise.all([this.updateAppServerURL()])
return this.updateAppServerURL()
.then(() =>
Promise.all([
this.subjectConfig.getParticipantLogin(),
Expand All @@ -46,16 +65,25 @@ export class AppServerService {
])
)
.then(([subjectId, projectId, enrolmentDate, attributes, fcmToken]) =>
this.addProjectIfMissing(projectId).then(() =>
this.addSubjectIfMissing(
subjectId,
projectId,
enrolmentDate,
attributes,
fcmToken
)
)
)
this.addProjectIfMissing(projectId)
.then(() => this.addSubjectIfMissing(
subjectId,
projectId,
enrolmentDate,
attributes,
fcmToken
)
).then(httpRes => {
if (this.tokenSubscription !== null) {
this.tokenSubscription.unsubscribe();
}
this.tokenSubscription = this.storage.observe(StorageKeys.FCM_TOKEN)
.pipe(filter(t => t && t !== fcmToken))
.subscribe(newFcmToken =>
this.addSubjectIfMissing(subjectId, projectId, enrolmentDate, attributes, newFcmToken))
return httpRes;
})
);
}

getHeaders() {
Expand Down Expand Up @@ -210,6 +238,205 @@ export class AppServerService {
})
}

getSchedule(): Promise<any> {
return Promise.all([
this.subjectConfig.getParticipantLogin(),
this.subjectConfig.getProjectName()
]).then(([subjectId, projectId]) => {
return this.getHeaders().then(headers =>
this.http
.get(
urljoin(
this.APP_SERVER_URL,
this.PROJECT_PATH,
projectId,
this.SUBJECT_PATH,
subjectId,
this.QUESTIONNAIRE_SCHEDULE_PATH
),
{ headers }
)
.toPromise()
)
})
}

getScheduleForDates(startTime: Date, endTime: Date): Promise<any> {
return Promise.all([
this.subjectConfig.getParticipantLogin(),
this.subjectConfig.getProjectName()
]).then(([subjectId, projectId]) => {
return this.getHeaders().then(headers =>
this.http
.get(
urljoin(
this.APP_SERVER_URL,
this.PROJECT_PATH,
projectId,
this.SUBJECT_PATH,
subjectId,
this.QUESTIONNAIRE_SCHEDULE_PATH
),
{
headers,
params: {
startTime: startTime.toISOString(),
endTime: endTime.toISOString()
}
}
)
.toPromise()
.catch(e => [])
)
})
}

generateSchedule(): Promise<any> {
return Promise.all([
this.subjectConfig.getParticipantLogin(),
this.subjectConfig.getProjectName()
]).then(([subjectId, projectId]) => {
return this.getHeaders().then(headers =>
this.http
.post(
urljoin(
this.APP_SERVER_URL,
this.PROJECT_PATH,
projectId,
this.SUBJECT_PATH,
subjectId,
this.QUESTIONNAIRE_SCHEDULE_PATH
),
{ headers }
)
.toPromise()
)
})
}

pullAllPublishedNotifications(subject) {
return this.getHeaders().then(headers =>
this.http
.get(
urljoin(
this.getAppServerURL(),
this.PROJECT_PATH,
subject.projectId,
this.SUBJECT_PATH,
subject.subjectId,
this.NOTIFICATIONS_PATH
),
{ headers }
)
.toPromise()
)
}

deleteNotification(subject, notification: SingleNotification) {
return this.getHeaders().then(headers =>
this.http
.delete(
urljoin(
this.getAppServerURL(),
this.PROJECT_PATH,
subject.projectId,
this.SUBJECT_PATH,
subject.subjectId,
this.NOTIFICATIONS_PATH,
notification.id.toString()
),
{ headers }
)
.toPromise()
)
}

updateTaskState(taskId, state) {
return Promise.all([
this.subjectConfig.getParticipantLogin(),
this.subjectConfig.getProjectName()
]).then(([subjectId, projectId]) => {
return this.getHeaders().then(headers =>
this.http
.post(
urljoin(
this.getAppServerURL(),
this.PROJECT_PATH,
projectId,
this.SUBJECT_PATH,
subjectId,
this.QUESTIONNAIRE_SCHEDULE_PATH,
taskId.toString(),
this.QUESTIONNAIRE_STATE_EVENTS_PATH
),
{
taskId: taskId,
state: state,
time: new Date(),
associatedInfo: ''
},
{ headers }
)
.toPromise()
)
})
}

updateNotificationState(subject, notificationId, state) {
return this.getHeaders().then(headers =>
this.http
.post(
urljoin(
this.getAppServerURL(),
this.PROJECT_PATH,
subject.projectId,
this.SUBJECT_PATH,
subject.subjectId,
this.NOTIFICATIONS_PATH,
notificationId.toString(),
this.STATE_EVENTS_PATH
),
{ notificationId: notificationId, state: state, time: new Date() },
{ headers }
)
.toPromise()
)
}

public addNotification(notification, subjectId, projectId): Promise<any> {
return this.getHeaders().then(headers =>
this.http
.post(
urljoin(
this.getAppServerURL(),
this.PROJECT_PATH,
projectId,
this.SUBJECT_PATH,
subjectId,
this.NOTIFICATIONS_PATH
),
notification.notificationDto,
{ headers, observe: 'response' }
)
.toPromise()
.then((res: HttpResponse<FcmNotificationDto>) => {
this.logger.log('Successfully sent! Updating notification Id')
return res.body
})
.catch((err: HttpErrorResponse) => {
this.logger.log('Http request returned an error: ' + err.message)
const data: FcmNotificationError = err.error
if (err.status == 409) {
this.logger.log(
'Notification already exists, storing notification data..'
)
return data.dto ? data.dto : notification.notification
}
return this.logger.error('Failed to send notification', err)
})
)
}

getFCMToken() {
return this.storage.get(StorageKeys.FCM_TOKEN)
}
Expand Down
6 changes: 4 additions & 2 deletions src/app/core/services/kafka/kafka.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TestBed } from '@angular/core/testing'

import {
FirebaseAnalyticsServiceMock,
LogServiceMock,
LogServiceMock, RemoteConfigServiceMock,
SchemaServiceMock,
StorageServiceMock,
TokenServiceMock
Expand All @@ -14,6 +14,7 @@ import { TokenService } from '../token/token.service'
import { AnalyticsService } from '../usage/analytics.service'
import { KafkaService } from './kafka.service'
import { SchemaService } from './schema.service'
import { RemoteConfigService } from "../config/remote-config.service";

describe('KafkaService', () => {
let service
Expand All @@ -31,7 +32,8 @@ describe('KafkaService', () => {
{
provide: AnalyticsService,
useClass: FirebaseAnalyticsServiceMock
}
},
{ provide: RemoteConfigService, useClass: RemoteConfigServiceMock },
]
})
)
Expand Down
Loading

0 comments on commit 5bc3d70

Please sign in to comment.