diff --git a/Makefile b/Makefile
index 6a8f07c17..43554155b 100644
--- a/Makefile
+++ b/Makefile
@@ -477,7 +477,6 @@ else
$(call upload,platformTranslation,@packages/openchs-android/translations/ka_IN.json)
endif
-
deploy_platform_translations_staging:
make deploy_translations server=https://staging.avniproject.org port=443 username=admin password=$(OPENCHS_STAGING_ADMIN_PASSWORD)
@@ -496,3 +495,6 @@ deploy_platform_translations_for_flavor_live:
deploy_platform_translations_live_for_all_flavors:
make deploy_platform_translations_for_flavor_live flavor='lfe'
make deploy_platform_translations_for_flavor_live flavor='generic'
+
+deploy_platform_translations_local_live:
+ make deploy_translations server=http://localhost port=8021 username=$(username) password=$(password)
diff --git a/packages/openchs-android/src/action/customDashboard/CustomDashboardActions.js b/packages/openchs-android/src/action/customDashboard/CustomDashboardActions.js
index d5a7bda5b..dacc630c5 100644
--- a/packages/openchs-android/src/action/customDashboard/CustomDashboardActions.js
+++ b/packages/openchs-android/src/action/customDashboard/CustomDashboardActions.js
@@ -49,7 +49,7 @@ class CustomDashboardActions {
loading: false,
reportCardSectionMappings: [],
cardToCountResultMap: {},
- countUpdateTime: null,
+ resultUpdatedAt: null,
hasFilters: false,
activeDashboardUUID: null,
customDashboardFilters: []
@@ -108,7 +108,7 @@ class CustomDashboardActions {
static setFilterApplied(state, action, context) {
const customDashboardCacheService = context.get(CustomDashboardCacheService);
customDashboardCacheService.clearResults(state.activeDashboardUUID);
- return CustomDashboardActions.refreshCount(state, action, context);
+ return state;
}
static setFilterCleared(state, action, context) {
@@ -132,7 +132,6 @@ class CustomDashboardActions {
const newState = {...state};
newState.cardToCountResultMap = {};
- newState.countUpdateTime = new Date(); //Update this to ensure reportCard count change is reflected
const ruleInputArray = context.get(DashboardFilterService).toRuleInputObjects(state.activeDashboardUUID, selectedFilterValues);
reportCardSectionMappings.forEach(rcm => {
@@ -168,7 +167,8 @@ class CustomDashboardActions {
}
General.logDebug('CustomDashboardActions', `${rcm.card.name} took ${new Date() - start} ms`);
});
- customDashboardCacheService.setDashboardUpdateCompleted(state.activeDashboardUUID);
+ const {dashboardCache} = customDashboardCacheService.getDashboardCache(state.activeDashboardUUID);
+ newState.resultUpdatedAt = dashboardCache.updatedAt;
return newState;
}
@@ -193,14 +193,33 @@ class CustomDashboardActions {
}
return state;
}
+
+ static forceRefresh(state, action, context) {
+ const customDashboardCacheService = context.get(CustomDashboardCacheService);
+ customDashboardCacheService.clearResults(state.activeDashboardUUID);
+ return state;
+ }
+
+ static clearCounts(state, action, context) {
+ const newState = {...state};
+ newState.cardToCountResultMap = {};
+ return newState;
+ }
}
-// This is not a reducer, just a code reuse mechanism
-export function performCustomDashboardActionAndRefresh(dispatcher, actionName, action) {
- dispatcher.dispatchAction(actionName, action);
+// These are not reducers, just a code reuse mechanism
+export function performCustomDashboardActionAndRefresh(dispatcher, actionName, payload) {
+ dispatcher.dispatchAction(actionName, payload);
setTimeout(() => dispatcher.dispatchAction(CustomDashboardActionNames.REFRESH_COUNT), 500);
}
+export function performCustomDashboardActionAndClearRefresh(dispatcher, actionName, payload) {
+ dispatcher.dispatchAction(actionName, payload);
+ dispatcher.dispatchAction(CustomDashboardActionNames.CLEAR_COUNTS, payload);
+ setTimeout(() => dispatcher.dispatchAction(CustomDashboardActionNames.REFRESH_COUNT), 500);
+}
+
+
const ActionPrefix = 'CustomDashboard';
const CustomDashboardActionNames = {
@@ -212,7 +231,9 @@ const CustomDashboardActionNames = {
SET_DASHBOARD_FILTERS: `${ActionPrefix}.SET_DASHBOARD_FILTERS`,
FILTER_APPLIED: `${ActionPrefix}.FILTER_APPLIED`,
FILTER_CLEARED: `${ActionPrefix}.FILTER_CLEARED`,
- DISABLE_AUTO_REFRESH_VALUE_UPDATED: `${ActionPrefix}.DISABLE_AUTO_REFRESH_VALUE_UPDATED`
+ DISABLE_AUTO_REFRESH_VALUE_UPDATED: `${ActionPrefix}.DISABLE_AUTO_REFRESH_VALUE_UPDATED`,
+ FORCE_REFRESH: `${ActionPrefix}.FORCE_REFRESH`,
+ CLEAR_COUNTS: `${ActionPrefix}.CLEAR_COUNTS`
};
const CustomDashboardActionMap = new Map([
@@ -224,7 +245,9 @@ const CustomDashboardActionMap = new Map([
[CustomDashboardActionNames.SET_DASHBOARD_FILTERS, CustomDashboardActions.setCustomDashboardFilters],
[CustomDashboardActionNames.FILTER_APPLIED, CustomDashboardActions.setFilterApplied],
[CustomDashboardActionNames.FILTER_CLEARED, CustomDashboardActions.setFilterCleared],
- [CustomDashboardActionNames.DISABLE_AUTO_REFRESH_VALUE_UPDATED, CustomDashboardActions.disableAutoRefreshValueUpdated]
+ [CustomDashboardActionNames.DISABLE_AUTO_REFRESH_VALUE_UPDATED, CustomDashboardActions.disableAutoRefreshValueUpdated],
+ [CustomDashboardActionNames.FORCE_REFRESH, CustomDashboardActions.forceRefresh],
+ [CustomDashboardActionNames.CLEAR_COUNTS, CustomDashboardActions.clearCounts]
]);
export {CustomDashboardActionNames, CustomDashboardActionMap, CustomDashboardActions}
diff --git a/packages/openchs-android/src/service/CustomDashboardCacheService.js b/packages/openchs-android/src/service/CustomDashboardCacheService.js
index b4477039b..b21fa36a2 100644
--- a/packages/openchs-android/src/service/CustomDashboardCacheService.js
+++ b/packages/openchs-android/src/service/CustomDashboardCacheService.js
@@ -1,9 +1,8 @@
import BaseService from "./BaseService";
import Service from "../framework/bean/Service";
-import {CustomDashboardCache, DashboardFilterConfig} from "openchs-models";
+import {CustomDashboardCache, Dashboard, DashboardFilterConfig, EncounterType, Program, Range, SubjectType} from "openchs-models";
import _ from "lodash";
import EntityService from "./EntityService";
-import {Dashboard, EncounterType, Range, Program, SubjectType} from "openchs-models";
import DashboardFilterService from "./reports/DashboardFilterService";
import General from "../utility/General";
import FormMetaDataSelection from "../model/FormMetaDataSelection";
@@ -138,6 +137,7 @@ class CustomDashboardCacheService extends BaseService {
result.reportCard = reportCard.uuid;
dashboardCache.nestedReportCardResults.push(result);
});
+ dashboardCache.updatedAt = new Date();
this.saveOrUpdate(dashboardCache);
}
@@ -145,6 +145,7 @@ class CustomDashboardCacheService extends BaseService {
const dashboardCache = getDashboardCache(this, dashboardUUID);
dashboardCache.reportCardResults = [];
dashboardCache.nestedReportCardResults = [];
+ dashboardCache.updatedAt = null;
this.saveOrUpdate(dashboardCache);
}
@@ -160,13 +161,8 @@ class CustomDashboardCacheService extends BaseService {
_.remove(dashboardCache.reportCardResults, (x) => x.reportCard === reportCard.uuid && x.dashboard === dashboardCache.dashboard.uuid);
reportCardResult.dashboard = dashboardUUID;
reportCardResult.reportCard = reportCard.uuid;
- dashboardCache.reportCardResults.push(reportCardResult);
- this.saveOrUpdate(dashboardCache);
- }
-
- setDashboardUpdateCompleted(dashboardUUID) {
- const dashboardCache = getDashboardCache(this, dashboardUUID);
dashboardCache.updatedAt = new Date();
+ dashboardCache.reportCardResults.push(reportCardResult);
this.saveOrUpdate(dashboardCache);
}
}
diff --git a/packages/openchs-android/src/service/SyncService.js b/packages/openchs-android/src/service/SyncService.js
index f872661a3..b43a36728 100644
--- a/packages/openchs-android/src/service/SyncService.js
+++ b/packages/openchs-android/src/service/SyncService.js
@@ -37,7 +37,10 @@ import AllSyncableEntityMetaData from "../model/AllSyncableEntityMetaData";
import {IndividualSearchActionNames as IndividualSearchActions} from '../action/individual/IndividualSearchActions';
import {LandingViewActionsNames as LandingViewActions} from '../action/LandingViewActions';
import {MyDashboardActionNames} from '../action/mydashboard/MyDashboardActions';
-import {CustomDashboardActionNames, performCustomDashboardActionAndRefresh} from '../action/customDashboard/CustomDashboardActions';
+import {
+ CustomDashboardActionNames,
+ performCustomDashboardActionAndClearRefresh,
+} from '../action/customDashboard/CustomDashboardActions';
import LocalCacheService from "./LocalCacheService";
import CustomDashboardService, {CustomDashboardType} from './customDashboard/CustomDashboardService';
@@ -412,7 +415,7 @@ class SyncService extends BaseService {
const customDashboardService = this.context.getService(CustomDashboardService);
const renderCustomDashboard = customDashboardService.isCustomDashboardMarkedPrimary();
if (renderCustomDashboard) {
- performCustomDashboardActionAndRefresh(this, CustomDashboardActionNames.ON_LOAD, {customDashboardType: CustomDashboardType.None});
+ performCustomDashboardActionAndClearRefresh(this, CustomDashboardActionNames.ON_LOAD, {customDashboardType: CustomDashboardType.None});
} else {
this.dispatchAction(MyDashboardActionNames.ON_LOAD);
}
diff --git a/packages/openchs-android/src/views/customDashboard/CustomDashboardView.js b/packages/openchs-android/src/views/customDashboard/CustomDashboardView.js
index 9a2167932..9f6b49885 100644
--- a/packages/openchs-android/src/views/customDashboard/CustomDashboardView.js
+++ b/packages/openchs-android/src/views/customDashboard/CustomDashboardView.js
@@ -3,7 +3,11 @@ import CHSContainer from "../common/CHSContainer";
import AppHeader from "../common/AppHeader";
import React, {Fragment} from "react";
import Reducers from "../../reducer";
-import {CustomDashboardActionNames as Actions, performCustomDashboardActionAndRefresh} from "../../action/customDashboard/CustomDashboardActions";
+import {
+ CustomDashboardActionNames as Actions,
+ performCustomDashboardActionAndClearRefresh,
+ performCustomDashboardActionAndRefresh
+} from "../../action/customDashboard/CustomDashboardActions";
import {SafeAreaView, ScrollView, StyleSheet, Text, TouchableNativeFeedback, View} from "react-native";
import _ from "lodash";
import CustomDashboardTab from "./CustomDashboardTab";
@@ -32,6 +36,7 @@ import MCIIcon from "react-native-vector-icons/MaterialCommunityIcons";
import Line from '../common/Line';
import {CardTileView} from './CardTileView';
import {CardListView} from './CardListView';
+import UserInfoService from "../../service/UserInfoService";
const viewNameMap = {
'ApprovalListingView': ApprovalListingView,
@@ -41,15 +46,37 @@ const viewNameMap = {
'ChecklistListingView': ChecklistListingView
};
+function RefreshSection({I18n, onRefreshPressed, lastUpdatedOn}) {
+ const refreshSectionStyle = {
+ paddingLeft: 15,
+ color: Styles.grey,
+ fontSize: 8,
+ fontWeight: 'bold',
+ textTransform: 'uppercase'
+ };
+ return onRefreshPressed()}>
+
+ {I18n.t('lastRefreshedMessage', {dateTime: General.formatDateTime(lastUpdatedOn)})}
+
+
+ ;
+}
+
function SubHeader({I18n, onFilterPressed}) {
const filterLabelStyle = {
paddingLeft: 15,
color: Styles.grey,
fontSize: Styles.normalTextSize,
fontWeight: 'bold',
- textTransform: 'uppercase'
+ textTransform: 'uppercase',
};
- return onFilterPressed()}>
+ return onFilterPressed()} style={{flex: 0.5}}>
{section.viewType !== DashboardSection.viewTypeName.Default &&
this.renderSectionName(section.name, section.description, section.viewType, cards)}
-
+
{_.map(cards, (card, index) => {
return section.viewType === 'Tile' ?
);
}
- renderFilters() {
- return this.state.filtersPresent && this.onFilterPressed()}/>;
- }
-
onFilterPressed() {
const {activeDashboardUUID} = this.state;
TypedTransition.from(this)
.with({
dashboardUUID: activeDashboardUUID,
- onFilterChosen: (ruleInputArray) => this.dispatchAction(Actions.FILTER_APPLIED, {ruleInput: {ruleInputArray: ruleInputArray}, filterApplied: true}),
+ onFilterChosen: (ruleInputArray) => performCustomDashboardActionAndClearRefresh(this, Actions.FILTER_APPLIED, {
+ ruleInput: {ruleInputArray: ruleInputArray},
+ filterApplied: true
+ }),
loadFiltersData: (filters) => this.dispatchAction(Actions.SET_DASHBOARD_FILTERS, {customDashboardFilters: filters, filterApplied: true}),
}).to(FiltersViewV2, true);
}
render() {
+ const settings = this.getService(UserInfoService).getUserSettingsObject();
General.logDebug("CustomDashboardView", "render");
const {hideBackButton, startSync, renderSync, icon, customDashboardType, onSearch, showSearch} = this.props;
const title = this.props.title || 'dashboards';
@@ -271,7 +298,13 @@ class CustomDashboardView extends AbstractComponent {
{this.renderZeroResultsMessageIfNeeded()}
}
- {this.renderFilters()}
+
+ {settings.autoRefreshDisabled && !_.isNil(this.state.resultUpdatedAt) &&
+ performCustomDashboardActionAndClearRefresh(this, Actions.FORCE_REFRESH)}
+ lastUpdatedOn={this.state.resultUpdatedAt}/>}
+ {this.state.filtersPresent && this.onFilterPressed()}/>}
+
{hasFilters &&
@@ -317,7 +350,7 @@ const styles = StyleSheet.create({
justifyContent: 'flex-start',
},
listContainer: {
- marginTop: 16
+ marginTop: 16
}
});
diff --git a/packages/openchs-android/translations/en.json b/packages/openchs-android/translations/en.json
index f089b5806..ba442070b 100644
--- a/packages/openchs-android/translations/en.json
+++ b/packages/openchs-android/translations/en.json
@@ -501,6 +501,7 @@
"addressFilterImplicitBehaviorHint": "(Selection includes lower levels implicitly)",
"copyErrorTryAgain": "Copy Error & Try Again",
"copyErrorAndCancel": "Copy Error & Cancel",
- "reportCopiedReportByPasting": "Report is copied. You can paste in a messaging app to report."
+ "reportCopiedReportByPasting": "Report is copied. You can paste in a messaging app to report.",
+ "lastRefreshedMessage": "Card numbers last updated on {{dateTime}"
}
}