| 1 |
if (!window.SequraFE) { |
| 2 |
window.SequraFE = {}; |
| 3 |
} |
| 4 |
|
| 5 |
SequraFE.appStates = { |
| 6 |
ONBOARDING: 'onboarding', |
| 7 |
SETTINGS: 'settings', |
| 8 |
PAYMENT: 'payment', |
| 9 |
TRANSACTION: 'transactions', |
| 10 |
ADVANCED: 'advanced' |
| 11 |
}; |
| 12 |
|
| 13 |
SequraFE.appPages = { |
| 14 |
ONBOARDING: { |
| 15 |
CONNECT: 'connect', |
| 16 |
COUNTRIES: 'countries', |
| 17 |
WIDGETS: 'widgets' |
| 18 |
}, |
| 19 |
SETTINGS: { |
| 20 |
GENERAL: 'general', |
| 21 |
CONNECTION: 'connection', |
| 22 |
ORDER_STATUS: 'order_status', |
| 23 |
WIDGET: 'widget' |
| 24 |
}, |
| 25 |
PAYMENT: { |
| 26 |
METHODS: 'methods' |
| 27 |
}, |
| 28 |
TRANSACTION: { |
| 29 |
LOGS: 'logs' |
| 30 |
}, |
| 31 |
ADVANCED: { |
| 32 |
DEBUG: 'debug' |
| 33 |
} |
| 34 |
}; |
| 35 |
|
| 36 |
(function () { |
| 37 |
/** |
| 38 |
* @typedef Store |
| 39 |
* @property {string} storeId |
| 40 |
* @property {string} storeName |
| 41 |
*/ |
| 42 |
|
| 43 |
/** |
| 44 |
* @typedef StateConfiguration |
| 45 |
* @property {string} stateUrl |
| 46 |
* @property {string} storesUrl |
| 47 |
* @property {string} currentStoreUrl |
| 48 |
* @property {string} getConnectionDataUrl |
| 49 |
* @property {string} versionUrl |
| 50 |
* @property {string} shopNameUrl |
| 51 |
* @property {Record<string, any>} pageConfiguration |
| 52 |
*/ |
| 53 |
|
| 54 |
/** |
| 55 |
* @typedef Version |
| 56 |
* @property {string} current |
| 57 |
* @property {string | null} new |
| 58 |
* @property {string | null} downloadNewVersionUrl |
| 59 |
*/ |
| 60 |
|
| 61 |
/** |
| 62 |
* @typedef ShopName |
| 63 |
* @property {string} shopName |
| 64 |
*/ |
| 65 |
|
| 66 |
/** |
| 67 |
* @typedef DataStore |
| 68 |
* @property {Version | null} version |
| 69 |
* @property {Store[] | null} stores |
| 70 |
* @property {ConnectionSettings | null} connectionSettings |
| 71 |
* @property {CountrySettings | null} countrySettings |
| 72 |
* @property {GeneralSettings | null} generalSettings |
| 73 |
* @property {OrderStatusMapping[] | null} orderStatusSettings |
| 74 |
* @property {WidgetSettings | null} widgetSettings |
| 75 |
* @property {PaymentMethod[] | null} paymentMethods |
| 76 |
* @property {SellingCountry[] | null} sellingCountries |
| 77 |
* @property {Category[] | null} shopCategories |
| 78 |
* @property {ShopOrderStatus[] | null} shopOrderStatuses |
| 79 |
* @property {ShopPaymentMethod[] | null} shopPaymentMethods |
| 80 |
* @property {TransactionLog[] | null} transactionLogs |
| 81 |
* @property {string[] | null} logs |
| 82 |
* @property {CountryPaymentMethod[] | null} allPaymentMethods |
| 83 |
*/ |
| 84 |
|
| 85 |
/** |
| 86 |
* Main controller of the application. |
| 87 |
* |
| 88 |
* @param {StateConfiguration} configuration |
| 89 |
* |
| 90 |
* @constructor |
| 91 |
*/ |
| 92 |
function StateController(configuration) { |
| 93 |
/** @type AjaxServiceType */ |
| 94 |
const api = SequraFE.ajaxService; |
| 95 |
const { pageControllerFactory, templateService, utilities } = SequraFE; |
| 96 |
|
| 97 |
let currentState = ''; |
| 98 |
let previousState = ''; |
| 99 |
|
| 100 |
/** |
| 101 |
* @type {DataStore} |
| 102 |
*/ |
| 103 |
let dataStore; |
| 104 |
|
| 105 |
const clearDataStore = () => { |
| 106 |
dataStore = { |
| 107 |
version: null, |
| 108 |
stores: null, |
| 109 |
connectionSettings: null, |
| 110 |
countrySettings: null, |
| 111 |
generalSettings: null, |
| 112 |
orderStatusSettings: null, |
| 113 |
widgetSettings: null, |
| 114 |
paymentMethods: null, |
| 115 |
sellingCountries: null, |
| 116 |
shopCategories: null, |
| 117 |
shopOrderStatuses: null, |
| 118 |
shopPaymentMethods: null, |
| 119 |
transactionLogs: null, |
| 120 |
logs: null, |
| 121 |
logsSettingsRes: null, |
| 122 |
allPaymentMethods: null |
| 123 |
}; |
| 124 |
} |
| 125 |
|
| 126 |
clearDataStore(); |
| 127 |
|
| 128 |
/** |
| 129 |
* Main entry point for the application. |
| 130 |
* Determines the current state and runs the start controller. |
| 131 |
*/ |
| 132 |
this.display = () => { |
| 133 |
utilities.showLoader(); |
| 134 |
clearDataStore(); |
| 135 |
templateService.clearMainPage(); |
| 136 |
|
| 137 |
window.addEventListener('hashchange', updateStateOnHashChange, false); |
| 138 |
|
| 139 |
api.get(configuration.currentStoreUrl, null, SequraFE.customHeader) |
| 140 |
.then( |
| 141 |
/** @param {Store|Store[]} response */ |
| 142 |
(response) => { |
| 143 |
const loadStore = (store) => { |
| 144 |
this.setStoreId(store.storeId); |
| 145 |
|
| 146 |
return displayPageBasedOnState(); |
| 147 |
}; |
| 148 |
|
| 149 |
let store = !Array.isArray(response) ? |
| 150 |
response : |
| 151 |
response.find((s) => s.storeId === this.getStoreId()); |
| 152 |
|
| 153 |
if (!store) { |
| 154 |
// the active store is probably deleted, we need to switch to the default store |
| 155 |
return api.get(configuration.currentStoreUrl, null, SequraFE.customHeader).then(loadStore); |
| 156 |
} |
| 157 |
|
| 158 |
return loadStore(store); |
| 159 |
} |
| 160 |
) |
| 161 |
}; |
| 162 |
|
| 163 |
/** |
| 164 |
* Updates the application state on a hash change. |
| 165 |
*/ |
| 166 |
const updateStateOnHashChange = () => { |
| 167 |
const state = window.location.hash.substring(1); |
| 168 |
state && this.goToState(state); |
| 169 |
}; |
| 170 |
|
| 171 |
/** |
| 172 |
* Opens a specific page based on the current state. |
| 173 |
*/ |
| 174 |
const displayPageBasedOnState = () => { |
| 175 |
utilities.showLoader(); |
| 176 |
const hasVersion = SequraFE?.integration?.hasVersion ?? true; |
| 177 |
const isMultistore = SequraFE?.integration?.isMultistore ?? true; |
| 178 |
|
| 179 |
return Promise.all([ |
| 180 |
hasVersion ? api.get(configuration.versionUrl.replace('{storeId}', this.getStoreId()), null, SequraFE.customHeader) : null, |
| 181 |
isMultistore ? api.get(configuration.storesUrl.replace('{storeId}', this.getStoreId()), null, SequraFE.customHeader) : null, |
| 182 |
api.get(configuration.pageConfiguration.onboarding.getConnectionDataUrl.replace('{storeId}', this.getStoreId()), null, SequraFE.customHeader), |
| 183 |
api.get(configuration.pageConfiguration.onboarding.getCountrySettingsUrl.replace('{storeId}', this.getStoreId()), null, SequraFE.customHeader), |
| 184 |
SequraFE.pages.onboarding.includes(SequraFE.appPages.ONBOARDING.WIDGETS) ? api.get(configuration.pageConfiguration.onboarding.getWidgetSettingsUrl.replace('{storeId}', this.getStoreId()), null, SequraFE.customHeader) : null, |
| 185 |
api.get(configuration.pageConfiguration.advanced.saveLogsSettingsUrl.replace('{storeId}', this.getStoreId()), null, SequraFE.customHeader), |
| 186 |
]).then(([versionRes, storesRes, connectionSettingsRes, countrySettingsRes, widgetSettingsRes, logsSettingsRes]) => { |
| 187 |
dataStore.version = versionRes; |
| 188 |
dataStore.stores = storesRes ?? []; |
| 189 |
dataStore.connectionSettings = connectionSettingsRes; |
| 190 |
dataStore.countrySettings = countrySettingsRes; |
| 191 |
dataStore.widgetSettings = widgetSettingsRes; |
| 192 |
dataStore.logsSettings = logsSettingsRes; |
| 193 |
return api.get(configuration.stateUrl.replace('{storeId}', this.getStoreId()), null, SequraFE.customHeader); |
| 194 |
}).then((stateRes) => { |
| 195 |
if (SequraFE.state.getCredentialsChanged()) { |
| 196 |
SequraFE.state.removeCredentialsChanged(); |
| 197 |
} |
| 198 |
|
| 199 |
let page = this.getPage(); |
| 200 |
if (stateRes.state === SequraFE.appStates.ONBOARDING) { |
| 201 |
this.goToState(SequraFE.appStates.ONBOARDING, null, true); |
| 202 |
|
| 203 |
return; |
| 204 |
} |
| 205 |
|
| 206 |
if (SequraFE.pages?.transactions?.includes(page)) { |
| 207 |
this.goToState(SequraFE.appStates.TRANSACTION + '-' + SequraFE.appPages.TRANSACTION.LOGS, null, true) |
| 208 |
|
| 209 |
return; |
| 210 |
} |
| 211 |
|
| 212 |
if (SequraFE.pages?.advanced?.includes(page)) { |
| 213 |
this.goToState(SequraFE.appStates.ADVANCED + '-' + page, null, true) |
| 214 |
return; |
| 215 |
} |
| 216 |
|
| 217 |
if (!page || SequraFE.pages.payment?.includes(page)) { |
| 218 |
this.goToState(SequraFE.appStates.PAYMENT + '-' + SequraFE.appPages.PAYMENT.METHODS, null, true) |
| 219 |
|
| 220 |
return; |
| 221 |
} |
| 222 |
|
| 223 |
this.goToState(SequraFE.appStates.SETTINGS + '-' + page, null, true); |
| 224 |
}).catch(e => { |
| 225 |
console.error(e); |
| 226 |
}); |
| 227 |
}; |
| 228 |
|
| 229 |
/** |
| 230 |
* Navigates to a state. |
| 231 |
* |
| 232 |
* @param {string} state |
| 233 |
* @param {Record<string, any> | null?} additionalConfig |
| 234 |
* @param {boolean} [force=false] |
| 235 |
*/ |
| 236 |
this.goToState = (state, additionalConfig = null, force = false) => { |
| 237 |
if ((currentState === state && !force)) { |
| 238 |
return; |
| 239 |
} |
| 240 |
|
| 241 |
utilities.showLoader(); |
| 242 |
let [controllerName, page] = state.split('-'); |
| 243 |
|
| 244 |
if (controllerName === SequraFE.appStates.ONBOARDING) { |
| 245 |
if ( |
| 246 |
dataStore.connectionSettings?.username && |
| 247 |
dataStore.countrySettings?.length && |
| 248 |
(!SequraFE.pages.onboarding.includes(SequraFE.appPages.ONBOARDING.WIDGETS) || dataStore.widgetSettings?.useWidgets !== undefined) && |
| 249 |
!SequraFE.state.getCredentialsChanged() |
| 250 |
) { |
| 251 |
currentState.split('-')[0] === SequraFE.appStates.ONBOARDING ? |
| 252 |
this.goToState(SequraFE.appStates.PAYMENT + '-' + SequraFE.appPages.PAYMENT.METHODS) : |
| 253 |
this.goToState(currentState, null, true); |
| 254 |
|
| 255 |
return; |
| 256 |
} |
| 257 |
|
| 258 |
if (!page) { |
| 259 |
page = SequraFE.appPages.ONBOARDING.WIDGETS; |
| 260 |
} |
| 261 |
|
| 262 |
switch (page) { |
| 263 |
case SequraFE.appPages.ONBOARDING.COUNTRIES: |
| 264 |
if (!dataStore.connectionSettings?.username) { |
| 265 |
page = SequraFE.appPages.ONBOARDING.CONNECT |
| 266 |
} |
| 267 |
|
| 268 |
break; |
| 269 |
case SequraFE.appPages.ONBOARDING.WIDGETS: |
| 270 |
if (dataStore.countrySettings?.length === 0 || SequraFE.state.getCredentialsChanged()) { |
| 271 |
page = SequraFE.appPages.ONBOARDING.COUNTRIES |
| 272 |
} |
| 273 |
|
| 274 |
if (!dataStore.connectionSettings?.username) { |
| 275 |
page = SequraFE.appPages.ONBOARDING.CONNECT |
| 276 |
} |
| 277 |
break; |
| 278 |
default: |
| 279 |
page = SequraFE.appPages.ONBOARDING.CONNECT |
| 280 |
} |
| 281 |
|
| 282 |
displayPage(controllerName + '-' + page, additionalConfig); |
| 283 |
|
| 284 |
return; |
| 285 |
} |
| 286 |
|
| 287 |
if ( |
| 288 |
!dataStore.connectionSettings?.username || |
| 289 |
dataStore.countrySettings?.length === 0 || |
| 290 |
(SequraFE.pages.onboarding.includes(SequraFE.appPages.ONBOARDING.WIDGETS) && dataStore.widgetSettings?.useWidgets === undefined) || |
| 291 |
SequraFE.state.getCredentialsChanged() |
| 292 |
) { |
| 293 |
this.goToState(SequraFE.appStates.ONBOARDING, additionalConfig, true); |
| 294 |
|
| 295 |
return; |
| 296 |
} |
| 297 |
|
| 298 |
displayPage(state, additionalConfig); |
| 299 |
}; |
| 300 |
|
| 301 |
const displayPage = (state, additionalConfig = null) => { |
| 302 |
let [controllerName, page] = state.split('-'); |
| 303 |
if (!Object.values(SequraFE.appStates).includes(controllerName)) { |
| 304 |
SequraFE.state.display(); |
| 305 |
} |
| 306 |
|
| 307 |
if (!page || !SequraFE.pages[controllerName]?.includes(page)) { |
| 308 |
page = SequraFE.pages[controllerName]?.[0]; |
| 309 |
state = page ? controllerName + '-' + page : controllerName; |
| 310 |
} |
| 311 |
|
| 312 |
const config = { storeId: this.getStoreId(), ...(additionalConfig || {}) }; |
| 313 |
const controller = pageControllerFactory.getInstance( |
| 314 |
controllerName, |
| 315 |
getControllerConfiguration(controllerName, page) |
| 316 |
); |
| 317 |
|
| 318 |
previousState = currentState; |
| 319 |
currentState = state; |
| 320 |
setPage(page); |
| 321 |
|
| 322 |
window.location.hash = state; |
| 323 |
controller && controller.display(config); |
| 324 |
} |
| 325 |
|
| 326 |
/** |
| 327 |
* Gets controller configuration. |
| 328 |
* |
| 329 |
* @param {string} controllerName |
| 330 |
* @param {string?} page |
| 331 |
* |
| 332 |
* @return {Record<string, any>} |
| 333 |
*/ |
| 334 |
const getControllerConfiguration = (controllerName, page) => { |
| 335 |
let config = utilities.cloneObject(configuration.pageConfiguration[controllerName] || {}); |
| 336 |
Object.keys(config).forEach((key) => { |
| 337 |
config[key] = config[key].replace('{storeId}', this.getStoreId); |
| 338 |
}) |
| 339 |
|
| 340 |
page && (config.page = page); |
| 341 |
|
| 342 |
return config; |
| 343 |
}; |
| 344 |
|
| 345 |
/** |
| 346 |
* Sets the application page to local storage. |
| 347 |
* |
| 348 |
* @param {string} page |
| 349 |
*/ |
| 350 |
const setPage = (page) => { |
| 351 |
localStorage.setItem('sq-page', page); |
| 352 |
} |
| 353 |
|
| 354 |
/** |
| 355 |
* Gets the application page from local storage. |
| 356 |
* |
| 357 |
* @returns {string} |
| 358 |
*/ |
| 359 |
this.getPage = () => { |
| 360 |
if (window.location.hash) { |
| 361 |
let page = window.location.hash.substring(1); |
| 362 |
if (page) { |
| 363 |
page = page.split('-')[1]; |
| 364 |
if (page) { |
| 365 |
setPage(page); |
| 366 |
return page; |
| 367 |
} |
| 368 |
} |
| 369 |
} |
| 370 |
return localStorage.getItem('sq-page'); |
| 371 |
} |
| 372 |
|
| 373 |
/** |
| 374 |
* Sets the credentials changed flag to local storage. |
| 375 |
*/ |
| 376 |
this.setCredentialsChanged = () => { |
| 377 |
SequraFE.state.setData('paymentMethods', null); |
| 378 |
SequraFE.state.setData('allPaymentMethods', null); |
| 379 |
localStorage.setItem('sq-password-changed', '1'); |
| 380 |
} |
| 381 |
|
| 382 |
/** |
| 383 |
* Removes the credentials changed flag from local storage. |
| 384 |
* |
| 385 |
* @returns {string} |
| 386 |
*/ |
| 387 |
this.removeCredentialsChanged = () => { |
| 388 |
localStorage.removeItem('sq-password-changed'); |
| 389 |
} |
| 390 |
|
| 391 |
/** |
| 392 |
* Gets the credentials changed flag from local storage. |
| 393 |
* |
| 394 |
* @returns {string} |
| 395 |
*/ |
| 396 |
this.getCredentialsChanged = () => { |
| 397 |
return localStorage.getItem('sq-password-changed'); |
| 398 |
} |
| 399 |
|
| 400 |
/** |
| 401 |
* Sets the store ID to local storage. |
| 402 |
* |
| 403 |
* @param {string} storeId |
| 404 |
*/ |
| 405 |
this.setStoreId = (storeId) => { |
| 406 |
sessionStorage.setItem('sq-active-store-id', storeId); |
| 407 |
}; |
| 408 |
|
| 409 |
/** |
| 410 |
* Gets the store ID from local storage. |
| 411 |
* |
| 412 |
* @returns {string} |
| 413 |
*/ |
| 414 |
this.getStoreId = () => { |
| 415 |
return sessionStorage.getItem('sq-active-store-id'); |
| 416 |
}; |
| 417 |
|
| 418 |
/** |
| 419 |
* Returns a getVersion promise. |
| 420 |
* |
| 421 |
* @returns {Promise<ShopName>} |
| 422 |
*/ |
| 423 |
this.getShopName = () => { |
| 424 |
return api.get(configuration.shopNameUrl, () => { |
| 425 |
}, SequraFE.customHeader); |
| 426 |
}; |
| 427 |
|
| 428 |
this.getData = (key) => { |
| 429 |
if (!Object.keys(dataStore).includes(key)) { |
| 430 |
return null; |
| 431 |
} |
| 432 |
|
| 433 |
return dataStore[key]; |
| 434 |
} |
| 435 |
|
| 436 |
this.setData = (key, value) => { |
| 437 |
if (Object.keys(dataStore).includes(key)) { |
| 438 |
dataStore[key] = value; |
| 439 |
} |
| 440 |
} |
| 441 |
} |
| 442 |
|
| 443 |
SequraFE.StateController = StateController; |
| 444 |
})(); |
| 445 |
|