Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React, { useCallback, useEffect, useState } from 'react';
import { ModalBody, ModalFooter, ModalHeader, Button, InlineLoading } from '@carbon/react';
import { useTranslation } from 'react-i18next';
import { getCurrentOfflineMode, showToast } from '@openmrs/esm-framework';

export interface OfflineActionsProgressModalProps {
items?: Array<any>;
closeModal: (active: boolean) => void;
}

const OfflineReadyModal: React.FC<OfflineActionsProgressModalProps> = ({ closeModal, items }) => {
const { t } = useTranslation();
const [isRunning, setIsRunning] = useState(true);
const [abortController, setAbortController] = useState(() => new AbortController());

async function dispatchOfflineEvent() {
window.dispatchEvent(
new CustomEvent(`openmrs:offline-enabled`, {
detail: getCurrentOfflineMode(),
}),
);

setIsRunning(false);
}

useEffect(() => {
dispatchOfflineEvent();
}, [abortController, items]);

const handleClose = useCallback(() => {
if (isRunning) {
abortController.abort();

showToast({
critical: true,
kind: 'warning',
description: t('unavailableOfflineFeatures', 'Some features may not be available offline.'),
title: t('offlinePreparationCanceled', 'Offline preparation canceled'),
});
closeModal(false);
} else {
showToast({
critical: true,
kind: 'success',
description: t('offlineModeIsReady', 'Offline mode is ready'),
title: t('offline', 'Offline'),
});
closeModal(true);
}
}, [abortController, closeModal, isRunning, t]);

return (
<>
<ModalHeader title={t('preparingOfflineMode', 'Preparing for offline mode')} closeModal={handleClose} />
<ModalBody>
{isRunning && (
<InlineLoading
// className={styles.loader}
description={t('loading', 'Loading') + '...'}
/>
)}
</ModalBody>
<ModalFooter>
<Button kind="danger" onClick={handleClose} disabled={!isRunning}>
{t('cancel', 'Cancel')}
</Button>
<Button kind="primary" onClick={handleClose} disabled={isRunning}>
{t('confirm', 'Confirm')}
</Button>
</ModalFooter>
</>
);
};

export default OfflineReadyModal;
12 changes: 10 additions & 2 deletions packages/apps/esm-offline-tools-app/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { defineConfigSchema, getSyncLifecycle, registerBreadcrumbs } from '@openmrs/esm-framework';
import {
defineConfigSchema,
getSyncLifecycle,
registerBreadcrumbs,
registerOfflineHandler,
} from '@openmrs/esm-framework';
import { routes } from './constants';
import { createDashboardLink } from './createDashboardLink';
import { dashboardMeta } from './dashboard.meta';
Expand All @@ -8,6 +13,7 @@ import offlineToolsComponent from './root.component';
import offlineToolsLinkComponent from './offline-tools-app-menu-link.component';
import offlineToolsNavItemsComponent from './nav/offline-tools-nav-menu.component';
import offlineToolsConfirmationModalComponent from './components/confirmation-modal.component';
import offlineToolsOfflineReadyModalComponent from './components/offline-ready-modal.component';
import offlineToolsPatientsCardComponent from './offline-patients/patients-overview-card.component';
import offlineToolsActionsCardComponent from './offline-actions/offline-actions-overview-card.component';
import offlineToolsActionsComponent from './offline-actions/offline-actions.component';
Expand Down Expand Up @@ -36,6 +42,8 @@ export const offlineToolsNavItems = getSyncLifecycle(offlineToolsNavItemsCompone

export const offlineToolsConfirmationModal = getSyncLifecycle(offlineToolsConfirmationModalComponent, options);

export const offlineToolsOfflineReadyModal = getSyncLifecycle(offlineToolsOfflineReadyModalComponent, options);

export const offlineToolsPatientsCard = getSyncLifecycle(offlineToolsPatientsCardComponent, options);

export const offlineToolsActionsCard = getSyncLifecycle(offlineToolsActionsCardComponent, options);
Expand Down Expand Up @@ -85,7 +93,7 @@ export const offlineToolsOptInButton = getSyncLifecycle(offlineToolsOptInButtonC

export function startupApp() {
defineConfigSchema(moduleName, {});
setupOffline();
registerOfflineHandler(setupOffline);
setupSynchronizingOfflineActionsNotifications();

registerBreadcrumbs([
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import React from 'react';
import React, { useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Toggle } from '@carbon/react';
import { Button } from '@carbon/react';
import { Network_3 } from '@carbon/react/icons';
import { getCurrentOfflineMode, setCurrentOfflineMode } from '@openmrs/esm-framework/src/internal';
import {
getCurrentOfflineMode,
setCurrentOfflineMode,
showModal,
useConnectivity,
} from '@openmrs/esm-framework/src/internal';
import styles from './offline-actions-mode-button.scss';
import { SwitcherItem } from '@carbon/react';

Expand All @@ -12,25 +17,41 @@ function doNotCloseMenu(ev: React.SyntheticEvent) {

const OfflineActionsModeButton: React.FC = () => {
const { t } = useTranslation();
const [active, setActive] = React.useState(() => getCurrentOfflineMode().active);
const toggle = React.useCallback(() => {
setActive((value) => {
const active = !value;
setCurrentOfflineMode(active ? 'on' : 'off');
return active;
const isOnline = useConnectivity();
const [active, setActive] = useState(() => getCurrentOfflineMode().active);

const toggle = useCallback(() => {
const dispose = showModal('offline-tools-offline-ready-modal', {
closeModal: (result) => {
setActive(result);
setCurrentOfflineMode(result ? 'on' : 'off');
dispose();
},
});
}, []);
}, [setActive]);

const handleRefresh = useCallback(() => {
toggle();
}, [toggle]);

return (
<SwitcherItem className={styles.panelItemContainer} aria-label="Offline mode">
<div>
<Network_3 size={20} />
<p onClick={doNotCloseMenu} role="none">
{t('offlineReady', 'Offline Ready')}
</p>
</div>
<Toggle className={styles.toggle} id="offlineModeSwitch" toggled={active} onToggle={toggle} />
</SwitcherItem>
isOnline && (
<SwitcherItem aria-label="Offline Ready" className={styles.panelItemContainer}>
<div>
<Network_3 size={20} />
<p>{t('offlineReady', 'Offline Ready')}</p>
</div>
{active ? (
<Button kind="ghost" onClick={handleRefresh}>
{t('refresh', 'Refresh')}
</Button>
) : (
<Button kind="ghost" id="offlineModeSwitch" onClick={toggle}>
{t('turnOn', 'Turn On')}
</Button>
)}
</SwitcherItem>
)
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,8 @@

.panelItemContainer a {
display: flex;
justify-content: space-between;
align-items: center;

:global(.cds--toggle-input__label .cds--toggle__switch) {
margin-top: 0 !important;
}

:global(.cds--toggle) {
/* setting the width prevents the toggle from changing size when the text changes */
width: 76px;
margin: 0 1rem;
}

:global(.cds--toggle__text) {
color: $ui-02;
}
justify-content: space-between;
}

.panelItemContainer div {
Expand Down
6 changes: 6 additions & 0 deletions packages/apps/esm-offline-tools-app/src/routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
"online": true,
"offline": true
},
{
"name": "offline-tools-offline-ready-modal",
"component": "offlineToolsOfflineReadyModal",
"online": true,
"offline": true
},
{
"name": "offline-tools-dashboard-patients-card",
"slot": "offline-tools-dashboard-cards",
Expand Down
11 changes: 11 additions & 0 deletions packages/apps/esm-offline-tools-app/translations/am.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"cancel": "Cancel",
"confirm": "Confirm",
"emptyStateText": "There are no {{displayText}} to display",
"home": "Home",
"homeHeader": "Offline home",
Expand All @@ -9,6 +11,10 @@
"homeOverviewCardPatientsHeader": "Patients",
"homeOverviewCardPatientsNewlyRegistered": "Newly registered",
"homeOverviewCardView": "View",
"lastRun": "Last Run",
"loading": "Loading",
"never": "Never",
"offline": "Offline",
"offlineActions": "Offline actions",
"offlineActionsDeleteConfirmationModalCancel": "Cancel",
"offlineActionsDeleteConfirmationModalConfirm": "Delete forever",
Expand All @@ -25,6 +31,7 @@
"offlineActionsTableError": "Error",
"offlineActionsTablePatient": "Patient",
"offlineActionsUpdateOfflinePatients": "Update offline patients",
"offlineModeIsReady": "Offline mode is ready",
"offlinePatients": "Offline patients",
"offlinePatients_lower": "offline patients",
"offlinePatientsHeader": "Offline patients",
Expand Down Expand Up @@ -52,8 +59,12 @@
"offlinePatientSyncDetailsFailedHeader": "There was an error downloading the following items",
"offlinePatientSyncDetailsFallbackErrorMessage": "Unknown error.",
"offlinePatientSyncDetailsHeader": "Offline patient details",
"offlinePreparationCanceled": "Offline preparation canceled",
"offlineReady": "Offline Ready",
"offlineToolsAppMenuLink": "Offline tools",
"preparingOfflineMode": "Preparing for offline mode",
"refresh": "Refresh",
"unavailableOfflineFeatures": "Some features may not be available offline.",
"offlineActionsSynchronizationNotificationTitle": "Upload",
"offlineActionsSynchronizationNotificationSynchronized": "The offline action synchronization has finished.",
"offlineActionsSynchronizationNotificationCanceling": "Canceling...",
Expand Down
11 changes: 11 additions & 0 deletions packages/apps/esm-offline-tools-app/translations/ar.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"cancel": "Cancel",
"confirm": "Confirm",
"emptyStateText": "لا يوجد {{displayText}} لعرضه",
"home": "الرئيسية",
"homeHeader": "الصفحة الرئيسية بدون اتصال",
Expand All @@ -9,6 +11,10 @@
"homeOverviewCardPatientsHeader": "المرضى",
"homeOverviewCardPatientsNewlyRegistered": "مُسجل حديثًا",
"homeOverviewCardView": "عرض",
"lastRun": "Last Run",
"loading": "Loading",
"never": "Never",
"offline": "Offline",
"offlineActions": "الأنشطة بدون اتصال",
"offlineActionsDeleteConfirmationModalCancel": "إلغاء",
"offlineActionsDeleteConfirmationModalConfirm": "حذف نهائي",
Expand All @@ -29,6 +35,7 @@
"offlineActionsTableError": "خطأ",
"offlineActionsTablePatient": "المريض",
"offlineActionsUpdateOfflinePatients": "تحديث المرضى بدون اتصال",
"offlineModeIsReady": "Offline mode is ready",
"offlinePatients": "المرضى بدون اتصال",
"offlinePatients_lower": "المرضى بدون اتصال",
"offlinePatientsHeader": "المرضى بدون اتصال",
Expand Down Expand Up @@ -56,8 +63,12 @@
"offlinePatientSyncDetailsFailedHeader": "حدث خطأ أثناء تحميل العناصر التالية",
"offlinePatientSyncDetailsFallbackErrorMessage": "خطأ غير معروف.",
"offlinePatientSyncDetailsHeader": "تفاصيل المريض بدون اتصال",
"offlinePreparationCanceled": "Offline preparation canceled",
"offlineReady": "جاهز للعمل بدون اتصال",
"offlineToolsAppMenuLink": "أدوات العمل بدون اتصال",
"preparingOfflineMode": "Preparing for offline mode",
"refresh": "Refresh",
"unavailableOfflineFeatures": "Some features may not be available offline.",
"offlineActionsSynchronizationNotificationTitle": "تحميل",
"offlineActionsSynchronizationNotificationSynchronized": "انتهت مزامنة الإجراءات غير المتصلة.",
"offlineActionsSynchronizationNotificationCanceling": "إلغاء...",
Expand Down
11 changes: 11 additions & 0 deletions packages/apps/esm-offline-tools-app/translations/en.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"cancel": "Cancel",
"confirm": "Confirm",
"emptyStateText": "There are no {{displayText}} to display",
"home": "Home",
"homeHeader": "Offline home",
Expand All @@ -9,6 +11,10 @@
"homeOverviewCardPatientsHeader": "Patients",
"homeOverviewCardPatientsNewlyRegistered": "Newly registered",
"homeOverviewCardView": "View",
"lastRun": "Last Run",
"loading": "Loading",
"never": "Never",
"offline": "Offline",
"offlineActions": "Offline Actions",
"offlineActionsDeleteConfirmationModalCancel": "Cancel",
"offlineActionsDeleteConfirmationModalConfirm": "Delete forever",
Expand All @@ -25,6 +31,7 @@
"offlineActionsTableError": "Error",
"offlineActionsTablePatient": "Patient",
"offlineActionsUpdateOfflinePatients": "Update offline patients",
"offlineModeIsReady": "Offline mode is ready",
"offlinePatients": "Offline patients",
"offlinePatients_lower": "offline patients",
"offlinePatientsHeader": "Offline patients",
Expand Down Expand Up @@ -52,8 +59,12 @@
"offlinePatientSyncDetailsFailedHeader": "There was an error downloading the following items",
"offlinePatientSyncDetailsFallbackErrorMessage": "Unknown error.",
"offlinePatientSyncDetailsHeader": "Offline patient details",
"offlinePreparationCanceled": "Offline preparation canceled",
"offlineReady": "Offline Ready",
"offlineToolsAppMenuLink": "Offline tools",
"preparingOfflineMode": "Preparing for offline mode",
"refresh": "Refresh",
"unavailableOfflineFeatures": "Some features may not be available offline.",
"offlineActionsSynchronizationNotificationTitle": "Upload",
"offlineActionsSynchronizationNotificationSynchronized": "The offline action synchronization has finished.",
"offlineActionsSynchronizationNotificationCanceling": "Canceling...",
Expand Down
11 changes: 11 additions & 0 deletions packages/apps/esm-offline-tools-app/translations/es.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"cancel": "Cancelar",
"confirm": "Confirmar",
"emptyStateText": "No hay {{displayText}} para mostrar",
"home": "Inicio",
"homeHeader": "Inicio offline",
Expand All @@ -9,6 +11,10 @@
"homeOverviewCardPatientsHeader": "Pacientes",
"homeOverviewCardPatientsNewlyRegistered": "Recién registrados",
"homeOverviewCardView": "Ver",
"lastRun": "Última carrera",
"loading": "Loading",
"never": "Nunca",
"offline": "Offline",
"offlineActions": "Acciones offline",
"offlineActionsDeleteConfirmationModalCancel": "Cancelar",
"offlineActionsDeleteConfirmationModalConfirm": "Eliminar para siempre",
Expand All @@ -26,6 +32,7 @@
"offlineActionsTableError": "Error",
"offlineActionsTablePatient": "Paciente",
"offlineActionsUpdateOfflinePatients": "Actualizar pacientes offline",
"offlineModeIsReady": "Offline mode is ready",
"offlinePatients": "Pacientes offline",
"offlinePatients_lower": "pacientes offline",
"offlinePatientsHeader": "Pacientes offline",
Expand Down Expand Up @@ -53,8 +60,12 @@
"offlinePatientSyncDetailsFailedHeader": "Hubo un error al descargar los siguientes elementos",
"offlinePatientSyncDetailsFallbackErrorMessage": "Error desconocido.",
"offlinePatientSyncDetailsHeader": "Detalles de pacientes offline",
"offlinePreparationCanceled": "Offline preparation canceled",
"offlineReady": "Listo offline",
"offlineToolsAppMenuLink": "Herramientas offline",
"preparingOfflineMode": "Preparando modo sin conexión",
"refresh": "Actualizar",
"unavailableOfflineFeatures": "Some features may not be available offline.",
"offlineActionsSynchronizationNotificationTitle": "Subir",
"offlineActionsSynchronizationNotificationSynchronized": "La sincronización de acciones sin conexión ha finalizado.",
"offlineActionsSynchronizationNotificationCanceling": "Cancelando...",
Expand Down
Loading