import string from 'dojo/string';
import DefaultMetrics from './DefaultMetrics';
import ErrorManager from 'argos/ErrorManager';
import environment from './Environment';
import SDKApplication from 'argos/Application';
import offlineManager from 'argos/Offline/Manager';
import MODEL_TYPES from 'argos/Models/Types';
import MODEL_NAMES from './Models/Names';
import BusyIndicator from 'argos/Dialogs/BusyIndicator';
import getResource from 'argos/I18n';
import MingleUtility from './MingleUtility';
import { app } from './reducers/index';
import { setConfig, setEndPoint } from './actions/config';
import { setUser } from './actions/user';
import PicklistService from './PicklistService';
const resource = getResource('application');
/**
* @alias crm.Application
* @extends argos.Application
*/
class Application extends SDKApplication {
constructor(options = {
connections: null,
defaultLocale: 'en',
enableUpdateNotification: false,
enableMultiCurrency: false,
multiCurrency: false, // Backwards compatibility
enableGroups: true,
enableHashTags: true,
maxUploadFileSize: 40000000,
enableConcurrencyCheck: false,
enableOfflineSupport: false,
warehouseDiscovery: 'auto',
enableMingle: false,
mingleEnabled: false, // Backwards compatibility
mingleSettings: null,
mingleRedirectUrl: '',
}) {
super();
this.navigationState = null;
this.rememberNavigationState = true;
this.speedSearch = {
includeStemming: true,
includePhonic: true,
includeThesaurus: false,
useFrequentFilter: false,
searchType: 1,
};
this.enableCaching = true;
this.userDetailsQuerySelect = ['UserName', 'UserInfo/UserName', 'UserInfo/FirstName', 'UserInfo/LastName', 'DefaultOwner/OwnerDescription'];
this.userOptionsToRequest = [
'category=DefaultGroup;name=ACCOUNT',
'category=DefaultGroup;name=CONTACT',
'category=DefaultGroup;name=OPPORTUNITY',
'category=DefaultGroup;name=LEAD',
'category=DefaultGroup;name=TICKET',
'category=DefaultGroup;name=SALESORDER',
'category=DefaultGroup;name=QUOTE',
'category=General;name=InsertSecCodeID',
'category=General;name=Currency',
'category=Calendar;name=DayStartTime',
'category=Calendar;name=WeekStart',
'category=ActivityMeetingOptions;name=AlarmEnabled',
'category=ActivityMeetingOptions;name=AlarmLead',
'category=ActivityMeetingOptions;name=Duration',
'category=ActivityPhoneOptions;name=AlarmEnabled',
'category=ActivityPhoneOptions;name=AlarmLead',
'category=ActivityPhoneOptions;name=Duration',
'category=ActivityToDoOptions;name=AlarmEnabled',
'category=ActivityToDoOptions;name=AlarmLead',
'category=ActivityToDoOptions;name=Duration',
'category=ActivityPersonalOptions;name=AlarmEnabled',
'category=ActivityPersonalOptions;name=AlarmLead',
'category=ActivityPersonalOptions;name=Duration',
];
this.systemOptionsToRequest = [
'BaseCurrency',
'MultiCurrency',
'ChangeOpportunityRate',
'LockOpportunityRate',
];
this.appName = 'argos-saleslogix';
this.serverVersion = {
major: 8,
minor: 0,
revision: 0,
};
this.mobileVersion = {
major: 4,
minor: 0,
revision: 0,
};
this.versionInfoText = resource.versionInfoText;
this.loadingText = resource.loadingText;
this.authText = resource.authText;
this.connectionToastTitleText = resource.connectionToastTitleText;
this.offlineText = resource.offlineText;
this.onlineText = resource.onlineText;
this.mingleAuthErrorText = resource.mingleAuthErrorText;
this.homeViewId = 'myactivity_list';
this.offlineHomeViewId = 'recently_viewed_list_offline';
this.loginViewId = 'login';
this.logOffViewId = 'logoff';
this.UID = null;
this.isAuthenticated = false;
this.hasState = false;
this.defaultViews = [
'myday_list',
'calendar_view',
'history_list',
'account_list',
'contact_list',
'lead_list',
'opportunity_list',
'ticket_list',
'myattachment_list',
'recently_viewed_list',
'briefcase_list',
];
// Settings
Object.assign(this, options); // TODO: Remove
// Save this config temporarily until we have a working store (init).
this._config = options;
}
init() {
// Must exist here for backwards compatibility for BOE Module
this.picklistService = PicklistService;
this._cachingService = new ICRMServicesSDK.CachingService(localStorage);
this.picklistService.init(this.getService(), this._cachingService);
super.init(...arguments);
// Dispatch the temp config we saved in the constructor
this.store.dispatch(setConfig(this._config));
this._config = null;
this._loadNavigationState();
let accessToken = null;
if (this.isMingleEnabled()) {
accessToken = this.mingleAuthResults.access_token;
}
this.UID = (new Date())
.getTime();
const original = Sage.SData.Client.SDataService.prototype.executeRequest;
const self = this;
Sage.SData.Client.SDataService.prototype.executeRequest = function executeRequest(request) {
if (accessToken) {
request.setRequestHeader('Authorization', `Bearer ${accessToken}`);
request.setRequestHeader('X-Authorization', `Bearer ${accessToken}`);
}
request.setRequestHeader('X-Application-Name', self.appName);
const version = self.mobileVersion;
const id = self.UID;
request.setRequestHeader('X-Application-Version', `${version.major}.${version.minor}.${version.revision};${id}`);
return original.apply(this, arguments);
};
}
initPreferences() {
super.initPreferences();
this._saveDefaultPreferences();
}
isMingleEnabled() {
return this.enableMingle || this.mingleEnabled;
}
getReducer() {
const sdk = super.getReducer(...arguments);
return Redux.combineReducers({
sdk,
app,
});
}
getInitialState() {
return {};
}
initConnects() {
super.initConnects(...arguments);
if (window.applicationCache) {
$(window.applicationCache).on('updateready', this._checkForUpdate.bind(this));
}
}
destroy() {
super.destroy();
$(window.applicationCache).off('updateready', this._checkForUpdate.bind(this));
}
isOnFirstView() {
const history = this.context.history;
const length = history.length;
const current = history[length - 1];
const previous = history[length - 2];
let isFirstView = false;
if ((current && current.page === this.loginViewId) || (current && current.page === this.logOffViewId)) {
isFirstView = true;
} else if (previous && previous.page === this.loginViewId) {
isFirstView = true;
} else if (length === 1) {
isFirstView = true;
}
return isFirstView;
}
onSetOrientation() {
// TODO: Close main nav like we did with left drawer?
}
_viewTransitionTo() {
super._viewTransitionTo(...arguments);
this._checkSaveNavigationState();
// TODO: Close main nav like we did with left drawer?
}
_checkSaveNavigationState() {
if (this.rememberNavigationState !== false) {
this._saveNavigationState();
}
}
_checkForUpdate() {
const applicationCache = window.applicationCache;
if (applicationCache && this.enableUpdateNotification) {
if (applicationCache.status === applicationCache.UPDATEREADY) {
this._notifyUpdateAvailable();
}
}
}
_notifyUpdateAvailable() {
if (this.bars.updatebar) {
this.bars.updatebar.show();
}
}
_saveNavigationState() {
try {
if (window.localStorage) {
window.localStorage.setItem('navigationState', JSON.stringify(ReUI.context.history));
}
} catch (e) {} // eslint-disable-line
}
hasMultiCurrency() {
// Check if the configuration specified multiCurrency, this will override the dynamic check.
// A configuration is not ideal, and we should refactor the edit view to process the layout when it first recieves its data,
// instead of on startup. We cannot check App.context data that was loaded after login when the startup method is used.
if (this.enableMultiCurrency || this.multiCurrency) {
return true;
}
return false;
}
canLockOpportunityRate() {
if (this.context &&
this.context.systemOptions &&
this.context.systemOptions.LockOpportunityRate === 'True') {
return true;
}
return false;
}
canChangeOpportunityRate() {
if (this.context &&
this.context.systemOptions &&
this.context.systemOptions.ChangeOpportunityRate === 'True') {
return true;
}
return false;
}
getMyExchangeRate() {
const results = {
code: '',
rate: 1,
};
if (this.hasMultiCurrency() &&
this.context &&
this.context.exchangeRates &&
this.context.userOptions &&
this.context.userOptions['General:Currency']) {
const myCode = this.context.userOptions['General:Currency'];
const myRate = this.context.exchangeRates[myCode];
Object.assign(results, {
code: myCode,
rate: myRate,
});
}
return results;
}
getBaseExchangeRate() {
const results = {
code: '',
rate: 1,
};
if (this.hasMultiCurrency() &&
this.context &&
this.context.exchangeRates &&
this.context.systemOptions &&
this.context.systemOptions.BaseCurrency) {
const baseCode = this.context.systemOptions.BaseCurrency;
const baseRate = this.context.exchangeRates[baseCode];
Object.assign(results, {
code: baseCode,
rate: baseRate,
});
}
return results;
}
getCurrentOpportunityExchangeRate() {
const results = {
code: '',
rate: 1,
};
let found = this.queryNavigationContext((o) => {
return (/^(opportunities)$/)
.test(o.resourceKind) && o.key;
});
found = found && found.options;
if (found) {
const rate = found.ExchangeRate;
const code = found.ExchangeRateCode;
Object.assign(results, {
code,
rate,
});
}
return results;
}
getCurrentLocale() {
return this.context.localization && this.context.localization.locale || this.defaultLocale;
}
run() {
super.run(...arguments);
if (this.isOnline() || !this.enableCaching) {
this.loadEndpoint();
if (this.isMingleEnabled()) {
this.handleMingleAuthentication();
} else {
this.handleAuthentication();
}
} else {
// todo: always navigate to home when offline? data may not be available for restored state.
this.navigateToHomeView();
}
if (this.enableUpdateNotification) {
this._checkForUpdate();
}
}
onAuthenticateUserSuccess(credentials, callback, scope, result) {
const user = {
$key: result.response.userId.trim(),
$descriptor: result.response.prettyName,
UserName: result.response.userName,
};
this.context.user = user;
this.context.roles = result.response.roles;
this.context.securedActions = result.response.securedActions;
if (this.context.securedActions) {
this.context.userSecurity = {};
this.context.securedActions.forEach((item) => {
this.context.userSecurity[item] = true;
});
} else {
// downgrade server version as only 8.0 has `securedActions` as part of the
// `getCurrentUser` response.
this.serverVersion = {
major: 7,
minor: 5,
revision: 4,
};
}
if (!this.isMingleEnabled() && credentials.remember) {
try {
if (window.localStorage) {
window.localStorage.setItem('credentials', Base64.encode(JSON.stringify({
username: credentials.username,
password: credentials.password || '',
endpoint: credentials.endpoint,
})));
}
} catch (e) {} //eslint-disable-line
}
if (callback) {
callback.call(scope || this, {
user,
});
}
}
onAuthenticateUserFailure(callback, scope, response) {
const service = this.getService();
if (service) {
service
.setUserName(false)
.setPassword(false);
}
if (callback) {
callback.call(scope || this, {
response,
});
}
}
authenticateUser(credentials, options) {
const service = this.getService();
if (credentials) {
service.setUserName(credentials.username)
.setPassword(credentials.password || '');
}
const request = new Sage.SData.Client.SDataServiceOperationRequest(service)
.setContractName('system')
.setOperationName('getCurrentUser');
request.execute({}, {
success: this.onAuthenticateUserSuccess.bind(this, credentials, options.success, options.scope),
failure: this.onAuthenticateUserFailure.bind(this, options.failure, options.scope),
aborted: this.onAuthenticateUserFailure.bind(this, options.failure, options.scope),
});
}
hasAccessTo(security) {
if (!security) {
return true;
}
const user = this.context.user;
const userId = user && user.$key;
const userSecurity = this.context.userSecurity;
if (/^ADMIN\s*/i.test(userId)) {
return true;
}
if (typeof userSecurity === 'undefined') {
return true; // running against a pre 8.0 SalesLogix environment
}
return !!userSecurity[security];
}
reload() {
// this.ReUI.disableLocationCheck();
this.hash('');
window.location.reload();
}
resetModuleAppStatePromises() {
this.clearAppStatePromises();
for (let i = 0; i < this.modules.length; i++) {
this.modules[i].loadAppStatePromises(this);
}
}
logOut() {
this.removeCredentials();
this._clearNavigationState();
const service = this.getService();
this.isAuthenticated = false;
this.context = {
history: [],
};
this.resetModuleAppStatePromises();
if (service) {
service
.setUserName(false)
.setPassword(false);
}
const view = this.getView(this.logOffViewId);
if (view) {
view.show();
}
}
getCredentials() {
let credentials = null;
try {
if (window.localStorage) {
const stored = window.localStorage.getItem('credentials');
const encoded = stored && Base64.decode(stored);
credentials = encoded && JSON.parse(encoded);
}
} catch (e) {} //eslint-disable-line
return credentials;
}
loadEndpoint() {
try {
if (window.localStorage) {
let results = window.localStorage.getItem('endpoint');
if (!results) {
const service = this.getService();
if (!this.isMingleEnabled()) {
service.uri.setHost(window.location.hostname)
.setScheme(window.location.protocol.replace(':', ''))
.setPort(window.location.port);
}
results = service.uri.build();
}
this.store.dispatch(setEndPoint(results));
}
} catch (e) {} // eslint-disable-line
}
saveEndpoint(url = '') {
if (!url) {
return;
}
try {
if (window.localStorage) {
window.localStorage.setItem('endpoint', url);
}
} catch (e) {} // eslint-disable-line
}
removeCredentials() {
try {
if (window.localStorage) {
window.localStorage.removeItem('credentials');
}
} catch (e) {} //eslint-disable-line
}
handleAuthentication() {
const credentials = this.getCredentials();
if (credentials) {
this.setPrimaryTitle(this.authText);
this.authenticateUser(credentials, {
success: this.onHandleAuthenticationSuccess,
failure: this.onHandleAuthenticationFailed,
aborted: this.onHandleAuthenticationAborted,
scope: this,
});
} else {
this.navigateToLoginView();
}
}
handleMingleAuthentication() {
if (this.mingleAuthResults && this.mingleAuthResults.error === 'access_denied') {
this.setPrimaryTitle(this.mingleAuthErrorText);
} else {
this.setPrimaryTitle(this.authText);
this.authenticateUser(null, {
success: this.onHandleAuthenticationSuccess,
failure: this.onMingleHandleAuthenticationFailed,
aborted: this.onHandleAuthenticationAborted,
scope: this,
});
}
}
onHandleAuthenticationSuccess() {
this.isAuthenticated = true;
this.setPrimaryTitle(this.loadingText);
this.showHeader();
this.initAppState().then(() => {
this.onInitAppStateSuccess();
}, (err) => {
this.onInitAppStateFailed(err);
});
}
showHeader() {
const header = $('.header', this.getContainerNode());
header.show();
}
onHandleAuthenticationFailed() {
this.removeCredentials();
this.navigateToLoginView();
}
onMingleHandleAuthenticationFailed() {
this.removeCredentials();
this.setPrimaryTitle(this.mingleAuthErrorText);
}
onHandleAuthenticationAborted() {
this.navigateToLoginView();
}
onInitAppStateSuccess() {
this.setDefaultMetricPreferences();
this.showApplicationMenuOnLarge();
if (this.enableOfflineSupport) {
this.initOfflineData().then(() => {
this.hasState = true;
this.navigateToInitialView();
}, (error) => {
this.hasState = true;
this.enableOfflineSupport = false;
const message = resource.offlineInitErrorText;
ErrorManager.addSimpleError(message, error);
ErrorManager.showErrorDialog(null, message, () => {
this.navigateToInitialView();
});
});
} else {
this.hasState = true;
this.navigateToInitialView();
}
}
onInitAppStateFailed(error) {
const message = resource.appStateInitErrorText;
ErrorManager.addSimpleError(message, error);
ErrorManager.showErrorDialog(null, message, () => {
this._clearNavigationState();
this.removeCredentials();
this.navigateToLoginView();
});
}
onStateChange(state) {
super.onStateChange(state);
if (!state || state === this.previousState) {
return;
}
const currentEndpoint = state.app.config.endpoint;
const previousEndpoint = this.previousState.app.config.endpoint;
if (currentEndpoint !== previousEndpoint) {
this.updateServiceUrl(state);
this.saveEndpoint(currentEndpoint);
}
}
updateServiceUrl(state) {
if (this.isMingleEnabled()) { // See TODO below, as to why we are bailing here
return;
}
const service = this.getService();
service.setUri(Object.assign({}, state.app.config.connections, {
url: state.app.config.endpoint, // TODO: Setting the URL here will break mingle instances that use custom virtual directories
}));
// Fixes cases where the user sets and invalid contract name in the url.
// We have a lot of requests throughout the application that do not specify
// a contractName and depend on the default contractName of "dynamic"
// in the service.
service.setContractName('dynamic');
service.setApplicationName('slx');
}
_clearNavigationState() {
try {
this.initialNavigationState = null;
if (window.localStorage) {
window.localStorage.removeItem('navigationState');
}
} catch (e) {} //eslint-disable-line
}
_loadNavigationState() {
try {
if (window.localStorage) {
this.navigationState = window.localStorage.getItem('navigationState');
}
} catch (e) {} // eslint-disable-line
}
_saveDefaultPreferences() {
if (this.preferences) {
return;
}
const views = this.getDefaultViews();
this.preferences = {
home: {
visible: views,
},
configure: {
order: views.slice(0),
},
};
}
getMetricsByResourceKind(resourceKind) {
let results = [];
let prefs = this.preferences && this.preferences.metrics && this.preferences.metrics;
if (prefs) {
prefs = prefs.filter((item) => {
return item.resourceKind === resourceKind;
});
if (prefs.length === 1) {
results = prefs[0].children;
}
}
return results;
}
setDefaultMetricPreferences() {
if (!this.preferences.metrics) {
const defaults = new DefaultMetrics();
this.preferences.metrics = defaults.getDefinitions();
this.persistPreferences();
}
}
clearMetricPreferences() {
this.preferences.metrics = null;
this.persistPreferences();
}
requestUserDetails() {
const key = this.context.user.$key;
const request = new Sage.SData.Client.SDataSingleResourceRequest(this.getService())
.setContractName('dynamic')
.setResourceKind('users')
.setResourceSelector(`"${key}"`)
.setQueryArg('select', this.userDetailsQuerySelect.join(','));
return new Promise((resolve, reject) => {
request.read({
success: function success(entry) {
this.store.dispatch(setUser(entry));
this.context.user = entry;
this.context.defaultOwner = entry && entry.DefaultOwner;
resolve(entry);
},
failure: function failure(e) {
reject(e);
},
scope: this,
});
});
}
requestUserOptions() {
const batch = new Sage.SData.Client.SDataBatchRequest(this.getService())
.setContractName('system')
.setResourceKind('useroptions')
.setQueryArg('select', 'name,value,defaultValue')
.using(function using() {
const service = this.getService();
this.userOptionsToRequest.forEach((item) => {
new Sage.SData.Client.SDataSingleResourceRequest(service)
.setContractName('system')
.setResourceKind('useroptions')
.setResourceKey(item)
.read();
});
}, this);
return new Promise((resolve, reject) => {
batch.commit({
success: function success(feed) {
const userOptions = this.context.userOptions = this.context.userOptions || {};
feed.$resources.forEach((item) => {
const key = item && item.$descriptor;
let { value } = item;
const { defaultValue } = item;
if (typeof value === 'undefined' || value === null) {
value = defaultValue;
}
if (key) {
userOptions[key] = value;
}
});
const insertSecCode = userOptions['General:InsertSecCodeID'];
const currentDefaultOwner = this.context.defaultOwner && this.context.defaultOwner.$key;
if (insertSecCode && (!currentDefaultOwner || (currentDefaultOwner !== insertSecCode))) {
this.requestOwnerDescription(insertSecCode);
}
this.loadCustomizedMoment();
resolve(feed);
},
failure: function failure(response, o) {
reject();
ErrorManager.addError(response, o, {}, 'failure');
},
scope: this,
});
});
}
/*
* Loads a custom object to pass into the current moment language. The object for the language gets built in buildCustomizedMoment.
*/
loadCustomizedMoment() {
const custom = this.buildCustomizedMoment();
const currentLang = moment.locale();
moment.locale(currentLang, custom);
this.moment = moment().locale(currentLang, custom);
}
/*
* Builds an object that will get passed into moment.locale()
*/
buildCustomizedMoment() {
if (!this.context.userOptions) {
return null;
}
const userWeekStartDay = parseInt(this.context.userOptions['Calendar:WeekStart'], 10);
let results = {}; // 0-6, Sun-Sat
if (!isNaN(userWeekStartDay)) {
results = {
week: {
dow: userWeekStartDay,
},
relativeTime: moment().locale(this.getCurrentLocale())._locale._relativeTime,
};
}
return results;
}
requestSystemOptions() {
const request = new Sage.SData.Client.SDataResourceCollectionRequest(this.getService())
.setContractName('system')
.setResourceKind('systemoptions')
.setQueryArg('select', 'name,value');
return new Promise((resolve, reject) => {
request.read({
success: function succes(feed) {
const systemOptions = this.context.systemOptions = this.context.systemOptions || {};
feed.$resources.forEach((item) => {
const { name, value } = item;
if (value && name && this.systemOptionsToRequest.indexOf(name) > -1) {
systemOptions[name] = value;
}
}, this);
const multiCurrency = systemOptions.MultiCurrency;
if (multiCurrency && multiCurrency === 'True') {
this.requestExchangeRates()
.then(() => {
resolve(feed);
}, () => {
reject();
});
} else {
resolve(feed);
}
},
failure: function failure(response, o) {
ErrorManager.addError(response, o, {}, 'failure');
reject();
},
scope: this,
});
});
}
requestExchangeRates() {
const request = new Sage.SData.Client.SDataResourceCollectionRequest(this.getService())
.setContractName('dynamic')
.setResourceKind('exchangeRates')
.setQueryArg('select', 'Rate');
return new Promise((resolve, reject) => {
request.read({
success: function success(feed) {
const exchangeRates = this.context.exchangeRates = this.context.exchangeRates || {};
feed.$resources.forEach((item) => {
const key = item && item.$descriptor;
const value = item && item.Rate;
if (value && key) {
exchangeRates[key] = value;
}
});
resolve(feed);
},
failure: function failure(response, o) {
reject();
ErrorManager.addError(response, o, {}, 'failure');
},
scope: this,
});
});
}
requestOwnerDescription(key) {
const request = new Sage.SData.Client.SDataSingleResourceRequest(this.getService())
.setContractName('dynamic')
.setResourceKind('owners')
.setResourceSelector(`"${key}"`)
.setQueryArg('select', 'OwnerDescription');
request.read({
success: this.onRequestOwnerDescriptionSuccess,
failure: this.onRequestOwnerDescriptionFailure,
scope: this,
});
}
onRequestOwnerDescriptionSuccess(entry) {
if (entry) {
this.context.defaultOwner = entry;
}
}
onRequestOwnerDescriptionFailure(response, o) {
ErrorManager.addError(response, o, {}, 'failure');
}
getDefaultViews() {
return this.defaultViews;
}
getExposedViews() {
return Object.keys(this.views).filter((id) => {
const view = this.getViewDetailOnly(id);
return view && view.id !== 'home' && view.expose;
});
}
cleanRestoredHistory(restoredHistory) {
let result = [];
let hasRoot = false;
for (let i = restoredHistory.length - 1; i >= 0 && !hasRoot; i--) {
if (restoredHistory[i].data.options && restoredHistory[i].data.options.negateHistory) {
result = [];
continue;
}
if (this.hasView(restoredHistory[i].page)) {
result.unshift(restoredHistory[i]);
}
hasRoot = (restoredHistory[i].page === 'home');
}
return hasRoot && result;
}
navigateToInitialView() {
this.showLeftDrawer();
this.showHeader();
try {
const restoredState = this.navigationState;
const restoredHistory = restoredState && JSON.parse(restoredState);
const cleanedHistory = this.cleanRestoredHistory(restoredHistory);
this._clearNavigationState();
if (cleanedHistory) {
ReUI.context.transitioning = true;
ReUI.context.history = ReUI.context.history.concat(cleanedHistory.slice(0, cleanedHistory.length - 1));
for (let i = 0; i < cleanedHistory.length - 1; i++) {
window.location.hash = cleanedHistory[i].hash;
}
ReUI.context.transitioning = false;
const last = cleanedHistory[cleanedHistory.length - 1];
const view = this.getView(last.page);
const options = last.data && last.data.options;
view.show(options);
} else {
this.navigateToHomeView();
}
} catch (e) {
this._clearNavigationState();
this.navigateToHomeView();
}
}
setupRedirectHash() {
let isMingleRefresh = false;
if (this._hasValidRedirect()) {
if (this.isMingleEnabled()) {
const vars = this.redirectHash.split('&');
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split('=');
if (pair[0] === 'state') {
if (pair[1] === 'mingleRefresh') { // show default view
isMingleRefresh = true;
} else {
this.redirectHash = decodeURIComponent(pair[1]);
}
break;
}
}
}
if (isMingleRefresh) {
const view = this.getView(App.getDefaultViews()[0]);
if (view) {
view.show();
}
} else {
// Split by "/redirectTo/"
const split = this.redirectHash.split(/\/redirectTo\//gi);
if (split.length === 2) {
this.redirectHash = split[1];
}
}
}
}
onConnectionChange(online) {
const view = this.getView('left_drawer');
if (!this.enableOfflineSupport) {
return;
}
if (this.isMingleEnabled() && online && this.requiresMingleRefresh) {
MingleUtility.refreshAccessToken(this);
return;
}
if (view) {
view.refresh();
}
if (online) {
this.toast.add({ message: this.onlineText, title: this.connectionToastTitleText });
if (this.context && this.context.user) {
this.navigateToInitialView();
} else {
this.navigateToLoginView();
}
} else {
this.toast.add({ message: this.offlineText, title: this.connectionToastTitleText });
this.navigateToInitialView();
}
this.setToolBarMode(online);
}
navigateToLoginView() {
this.setupRedirectHash();
const view = this.getView(this.loginViewId);
if (view) {
view.show();
}
}
_hasValidRedirect() {
const hashValue = decodeURIComponent(this.redirectHash);
return hashValue !== '' && hashValue.indexOf('/redirectTo/') > 0;
}
showLeftDrawer() {
const view = this.getView('left_drawer');
if (view) {
view.show();
}
return this;
}
showRightDrawer() {
return this;
}
navigateToHomeView() {
this.setupRedirectHash();
this.showLeftDrawer();
const visible = this.preferences && this.preferences.home && this.preferences.home.visible;
if (visible && visible.length > 0) {
this.homeViewId = visible[0];
}
// Default view will be the home view, overwritten below if a redirect hash is supplied
let view = this.getView(this.homeViewId);
if (this.redirectHash) {
let split = this.redirectHash.split(';');
if (split.length === 1) {
split = this.redirectHash.split(':');
}
if (split.length > 0) {
const [viewId, key] = split;
const redirectView = this.getView(viewId);
if (redirectView) {
if (!redirectView.canRedirectTo) {
// The user will go to the default view instead
view = this.getView(this.homeViewId);
} else {
view = redirectView;
if (key) {
redirectView.show({
key,
});
}
}
}
}
this.redirectHash = '';
}
if (!this.isOnline()) {
view = this.getView(this.offlineHomeViewId);
}
if (view) {
view.show();
}
}
navigateToActivityInsertView() {
const view = this.getView('activity_types_list');
if (view) {
view.show();
}
}
initiateCall() {
// shortcut for environment call
environment.initiateCall.apply(this, arguments);
}
initiateEmail() {
// shortcut for environment call
environment.initiateEmail.apply(this, arguments);
}
showMapForAddress() {
// shortcut for environment call
environment.showMapForAddress.apply(this, arguments);
}
getVersionInfo() {
const info = string.substitute(this.versionInfoText, [
this.mobileVersion.major,
this.mobileVersion.minor,
this.mobileVersion.revision,
this.serverVersion.major,
]);
return info;
}
initOfflineData() {
return new Promise((resolve, reject) => {
const model = this.ModelManager.getModel(MODEL_NAMES.AUTHENTICATION, MODEL_TYPES.OFFLINE);
if (model) {
const indicator = new BusyIndicator({
id: 'busyIndicator__offlineData',
label: resource.offlineInitDataText,
});
this.modal.disableClose = true;
this.modal.showToolbar = false;
this.modal.add(indicator);
indicator.start();
model.initAuthentication(this.context.user.$key).then((result) => {
let options = offlineManager.getOptions();
if (result.hasUserChanged) {
options = {
clearAll: true,
};
}
if (result.hasUserChanged || (!result.hasAuthenticatedToday)) {
offlineManager.clearData(options).then(() => {
model.updateEntry(result.entry);
indicator.complete(true);
this.modal.disableClose = false;
this.modal.hide();
resolve();
}, (err) => {
indicator.complete(true);
this.modal.disableClose = false;
this.modal.hide();
reject(err);
});
} else {
result.entry.ModifyDate = moment().toDate();
model.updateEntry(result.entry);
indicator.complete(true);
this.modal.disableClose = false;
this.modal.hide();
resolve(); // Do nothing since this not the first time athuenticating.
}
}, (err) => {
reject(err);
});
} else {
resolve();
}
});
}
}
export default Application;