Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion webapp/src/ts/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,11 @@ export class AppComponent implements OnInit, AfterViewInit {
}

private initAndroidTaskNotifications() {
if (typeof globalThis?.medicmobile_android?.updateTaskNotificationStore === 'function') {
const android = globalThis?.medicmobile_android;
if (
typeof android?.updateTaskNotificationStoreWithSettings === 'function' ||
typeof android?.updateTaskNotificationStore === 'function'
) {
this.taskNotificationService.initOnAndroid();
}
}
Expand Down
4 changes: 3 additions & 1 deletion webapp/src/ts/services/rules-engine.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ interface TaskDoc {
_id: string;
emission?: any;
owner: string;
stateHistory: Array<{ state: string, timestamp: number }>;
stateHistory: StateHistory;
}

export type StateHistory = Array<{ state: string, timestamp: number }>;

@Injectable({
providedIn: 'root'
})
Expand Down
41 changes: 35 additions & 6 deletions webapp/src/ts/services/task-notifications.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { Subscription } from 'rxjs';
import { debounce as _debounce } from 'lodash-es';
import * as moment from 'moment';

import { RulesEngineService } from '@mm-services/rules-engine.service';
import { RulesEngineService, StateHistory } from '@mm-services/rules-engine.service';
import { TranslateService } from '@mm-services/translate.service';
import { FormatDateService } from '@mm-services/format-date.service';
import { SettingsService } from '@mm-services/settings.service';
import { AuthService } from '@mm-services/auth.service';
import { orderByDueDateAndPriority } from '@mm-reducers/tasks';

const DEFAULT_MAX_NOTIFICATIONS = 8;
const DEFAULT_WINDOW_START_TIME = '08:00';
const DEFAULT_WINDOW_END_TIME = '19:00';

export interface Notification {
_id: string,
Expand All @@ -21,6 +23,14 @@ export interface Notification {
readyAt: number
}

export type notificationSettings = {
maxNotifications: number;
notificationWindow: {
start: string;
end: string;
}
};

@Injectable({
providedIn: 'root'
})
Expand Down Expand Up @@ -64,7 +74,15 @@ export class TasksNotificationService implements OnDestroy {

private async updateAndroidStore(): Promise<void> {
const notifications = await this.fetchNotifications();
const maxNotifications = await this.getMaxNotificationSettings();
const { maxNotifications, notificationWindow } = await this.getNotificationSettings();

if (globalThis?.medicmobile_android?.updateTaskNotificationStoreWithSettings) {
globalThis.medicmobile_android.updateTaskNotificationStoreWithSettings(
JSON.stringify(notifications),
JSON.stringify({maxNotifications, ...notificationWindow}),
);
return;
}
globalThis?.medicmobile_android?.updateTaskNotificationStore(JSON.stringify(notifications), maxNotifications);
}

Expand Down Expand Up @@ -97,17 +115,28 @@ export class TasksNotificationService implements OnDestroy {
}
}

private getReadyStateTimestamp(stateHistory): number {
private getReadyStateTimestamp(stateHistory: StateHistory): number {
const readyState = stateHistory.find(state => state.state === 'Ready');
return readyState ? readyState.timestamp : 0;
}

private async getMaxNotificationSettings(): Promise<number> {
private async getNotificationSettings(): Promise<notificationSettings> {
const settings = await this.settingsService.get();
const taskNotificationSettings: notificationSettings = {
maxNotifications: DEFAULT_MAX_NOTIFICATIONS,
notificationWindow: {
start: DEFAULT_WINDOW_START_TIME,
end: DEFAULT_WINDOW_END_TIME,
}
};
if (settings?.tasks?.max_task_notifications) {
return settings.tasks.max_task_notifications;
taskNotificationSettings.maxNotifications = settings.tasks.max_task_notifications;
}

if (settings.tasks?.task_notification_window) {
taskNotificationSettings.notificationWindow = settings.tasks.task_notification_window;
}
return DEFAULT_MAX_NOTIFICATIONS;
return taskNotificationSettings;
}

private translateContentText(taskTitle: string, contact: string): string {
Expand Down
7 changes: 7 additions & 0 deletions webapp/tests/karma/ts/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,13 @@ describe('AppComponent', () => {
expect(tasksNotificationService.initOnAndroid.callCount).to.equal(1);
});

it('should init task notifications on android if updateTaskNotificationStoreWithSettings', async () => {
window.medicmobile_android = { updateTaskNotificationStoreWithSettings: sinon.stub().returns(true) };
await getComponent();
await component.setupPromise;
expect(tasksNotificationService.initOnAndroid.callCount).to.equal(1);
});

it('should show reload popup when service worker is updated', async () => {
await getComponent();
await component.setupPromise;
Expand Down
63 changes: 58 additions & 5 deletions webapp/tests/karma/ts/services/task-notification.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,22 +127,25 @@ describe('TasksNotificationService', () => {
expect(service).to.be.ok;
});

it('should initialize max notifications value from settings', async () => {
it('should initialize notifications values from settings', async () => {
settingsService.get.resolves({
tasks: {
max_task_notifications: 20
max_task_notifications: 20,
task_notification_window: { start: '10:00', end: '18:00' }
}
});
const maxNotifications = await service.getMaxNotificationSettings();
const { maxNotifications, notificationWindow } = await service.getNotificationSettings();
expect(settingsService.get.callCount).to.equal(1);
expect(maxNotifications).to.equal(20);
expect(notificationWindow).to.deep.equal({ start: '10:00', end: '18:00' });
});

it('should return default max notifications value if settings value is not valid', async () => {
it('should return default notification values if settings value is not valid', async () => {
settingsService.get.resolves({ max_task_notifications: '2o' });
const maxNotifications = await service.getMaxNotificationSettings();
const { maxNotifications, notificationWindow } = await service.getNotificationSettings();
expect(settingsService.get.callCount).to.equal(1);
expect(maxNotifications).to.equal(8);
expect(notificationWindow).to.deep.equal({ start: '08:00', end: '19:00' });
});

it('should fetch notifications', async () => {
Expand Down Expand Up @@ -259,4 +262,54 @@ describe('TasksNotificationService', () => {
expect(updateAndroidStoreStub.callCount).to.equal(0);
});

describe('updateAndroidStore', () => {
let androidApi: any;

beforeEach(() => {
androidApi = {};
(globalThis as any).medicmobile_android = androidApi;
});

afterEach(() => {
delete (globalThis as any).medicmobile_android;
});

it('should update the android store without settings when only the basic api is available', async () => {
androidApi.updateTaskNotificationStore = sinon.stub();

await service.updateAndroidStore();

expect(androidApi.updateTaskNotificationStore.callCount).to.equal(1);

const [notificationsJson, maxNotifications] = androidApi.updateTaskNotificationStore.args[0];
expect(JSON.parse(notificationsJson)).to.be.an('array').that.has.lengthOf(3);
expect(maxNotifications).to.equal(8);
});

it('should update the android store with settings when the settings api is available', async () => {
androidApi.updateTaskNotificationStore = sinon.stub();
androidApi.updateTaskNotificationStoreWithSettings = sinon.stub();
settingsService.get.resolves({
tasks: {
max_task_notifications: 20,
task_notification_window: { start: '10:00', end: '18:00' },
},
});

await service.updateAndroidStore();

expect(androidApi.updateTaskNotificationStore.callCount).to.equal(0);
expect(androidApi.updateTaskNotificationStoreWithSettings.callCount).to.equal(1);

const [notificationsJson, settingsJson] =
androidApi.updateTaskNotificationStoreWithSettings.args[0];
expect(JSON.parse(notificationsJson)).to.be.an('array').that.has.lengthOf(3);
expect(JSON.parse(settingsJson)).to.deep.equal({
maxNotifications: 20,
start: '10:00',
end: '18:00'
});
});
});

});