helper.js (13017B)
1 import kebabCase from 'lodash/kebabCase' 2 import uniq from 'lodash/uniq'; 3 import concat from 'lodash/concat'; 4 import flatten from 'lodash/flatten'; 5 import sortBy from 'lodash/sortBy'; 6 import map from 'lodash/map'; 7 import flattenDeep from 'lodash/flattenDeep'; 8 import {afterImportHandling} from './actionHelper'; 9 import {getPluginInstance, isPluginReduxProMerged} from './dependencyHelper'; 10 const {createBlock} = wp.blocks; 11 const {dispatch} = wp.data; 12 const {createSuccessNotice} = dispatch('core/notices'); 13 const {insertBlocks} = dispatch('core/block-editor'); 14 15 const prefix = 'redux_'; 16 export const REDUXTEMPLATES_PRO_KEY = 'redux-pro'; 17 export const NONE_KEY = 'core'; 18 const EXIPRY_TIME = 5 * 24 * 3600 * 1000; 19 20 export const getCurrentState = (state) => state[state.activeItemType] 21 // Helper function not to be exported 22 const convertObjectToArray = (list) => { 23 if (!list) 24 return []; 25 return Object.keys(list).map(key => { 26 return {...list[key], ID: key}; 27 }) 28 }; 29 30 // parse categories and section data from section server data 31 export const categorizeData = (list) => { 32 let categories = []; 33 let data = {}; 34 35 list.forEach(item => { 36 if (item.categories) { 37 item.categories.map(catName => { 38 let catSlug = kebabCase(catName); 39 if (catSlug in data) { 40 data[catSlug].push(item) 41 } else { 42 data[catSlug] = []; 43 data[catSlug].push(item) 44 } 45 let index = -1; 46 categories.forEach((change, i) => { 47 if (catSlug == change.slug) { 48 index = i 49 categories[i].ids.push(item.id); 50 } 51 }); 52 if (index === -1) { 53 categories.push({name: catName, slug: catSlug, ids: [item.id]}) 54 } 55 }) 56 } 57 }); 58 59 return {categories, data}; 60 } 61 62 /* Parse section data */ 63 // - convert `sections` object to array 64 // - make fullPluginsList from dependency, like ['redux-pro', 'qubely', 'getwid', ...] 65 // -- filter wholePlugins from fullPluginsList 66 // -- filter thirdPartyPlugins from fullPluginsList 67 // - categorize the plugin information and save it to local storage 68 export const parseSectionData = (sections) => { 69 const librarySectionData = convertObjectToArray(sections); 70 const fullPluginsList = uniq(flattenDeep(map(librarySectionData, 'dependencies'))); 71 const wholePlugins = fullPluginsList.filter(pluginKey => !isThirdPartyPlugin(pluginKey)); 72 const thirdPartyPlugins = fullPluginsList.filter(pluginKey => isThirdPartyPlugin(pluginKey)); 73 const toBeReturned = categorizeData(librarySectionData); 74 const categoriesList = toBeReturned.categories.map((category) => {return {label: category.name, value: category.slug}; }); 75 setWithExpiry('section_categories_list', categoriesList, EXIPRY_TIME); 76 return {...toBeReturned, wholePlugins, thirdPartyPlugins}; 77 } 78 79 export const parsePageData = (pages) => { 80 const libraryPageData = convertObjectToArray(pages); 81 const fullPluginsList = uniq(flattenDeep(map(libraryPageData, 'dependencies'))); 82 const wholePlugins = fullPluginsList.filter(pluginKey => !isThirdPartyPlugin(pluginKey)); 83 const thirdPartyPlugins = fullPluginsList.filter(pluginKey => isThirdPartyPlugin(pluginKey)); 84 const toBeReturned = categorizeData(libraryPageData); 85 const categoriesList = toBeReturned.categories.map((category) => {return {label: category.name, value: category.slug}; }); 86 setWithExpiry('page_categories_list', categoriesList, EXIPRY_TIME); 87 return {...toBeReturned, wholePlugins, thirdPartyPlugins}; 88 } 89 90 export const parseCollectionData = (library) => { 91 let libraryCollectionData = convertObjectToArray(library.collections); 92 // filter out incomplete data 93 libraryCollectionData = libraryCollectionData.filter(collection => collection.pages && collection.pages.length > 0); 94 // After common handling, we need to populate homepage data 95 libraryCollectionData = libraryCollectionData.map(collection => { 96 if (collection.homepage && library.pages[collection.homepage]) collection.homepageData = library.pages[collection.homepage]; 97 else { 98 collection.homepageData = library.pages[collection.pages[0]]; 99 } 100 101 if (collection.pages) { 102 collection.installDependenciesMissing = uniq(concat(flatten(collection.pages.map(page => library.pages[page].installDependenciesMissing || [])))); 103 collection.proDependenciesMissing = uniq(concat(flatten(collection.pages.map(page => library.pages[page].proDependenciesMissing || [])))); 104 } 105 106 return collection; 107 }); 108 const fullPluginsList = uniq(flattenDeep(map(libraryCollectionData, 'dependencies'))); 109 const wholePlugins = fullPluginsList.filter(pluginKey => !isThirdPartyPlugin(pluginKey)); 110 const thirdPartyPlugins = fullPluginsList.filter(pluginKey => isThirdPartyPlugin(pluginKey)); 111 return {...categorizeData(libraryCollectionData), dependencyFilters: {[NONE_KEY]: true, ...library.dependencies}, wholePlugins, thirdPartyPlugins}; 112 } 113 114 // one of important function 115 // get collection children data upon clicking on collection in collections tab 116 // always homepage page first, sort alphabetically afterward 117 export const getCollectionChildrenData = (library, activeCollection) => { 118 let activeCollectionData = library.collections[activeCollection]; 119 // sort page except homepage 120 let childrenPages = activeCollectionData.pages 121 .filter(page => page !== activeCollectionData.homepage) 122 .map(child => { 123 return {...library.pages[child], ID: child} 124 }); 125 childrenPages = sortBy(childrenPages, 'name'); 126 // insert homepage at the beginning of the array 127 if (activeCollectionData.homepage && library.pages[activeCollectionData.homepage]) { 128 childrenPages.unshift(library.pages[activeCollectionData.homepage]); 129 } 130 return childrenPages; 131 } 132 133 // Check if the block is pro 134 export const isBlockPro = (pro, source) => { 135 if (source && redux_templates.supported_plugins.hasOwnProperty(source)) 136 return (pro && !redux_templates.supported_plugins[source].is_pro); 137 else 138 return pro && redux_templates.mokama !== '1'; 139 } 140 141 export const missingPro = (pro) => { 142 return (redux_templates.mokama !== '1' && pro === true); 143 } 144 145 export const missingRequirement = (pro, requirements) => { 146 if (!requirements) return missingPro(pro); 147 else { 148 const supported_plugins = redux_templates.supported_plugins; 149 for (let i = 0; i < requirements.length; i++) { 150 let requirement = requirements[i]; 151 if (!supported_plugins.hasOwnProperty(requirement.slug)) 152 return true; // Doesn't have the plugin installed 153 else { 154 let installedPlugin = supported_plugins[requirement.slug]; 155 if (Number(requirement.version) > Number(installedPlugin.version) || 156 (requirement.pro === true && installedPlugin.pro === false)) 157 return true; 158 } 159 } 160 return proCheck; 161 } 162 } 163 164 165 export const setWithExpiry = (key, value, ttl) => { 166 const prefixedKey = prefix + key; 167 const now = new Date(); 168 169 // `item` is an object which contains the original value 170 // as well as the time when it's supposed to expire 171 const item = { 172 value: value, 173 expiry: now.getTime() + ttl 174 }; 175 localStorage.setItem(prefixedKey, JSON.stringify(item)); 176 } 177 178 export const getWithExpiry = (key, defaultValue = null) => { 179 const prefixedKey = prefix + key; 180 const itemStr = localStorage.getItem(prefixedKey); 181 182 // if the item doesn't exist, return null 183 if (!itemStr) { 184 return defaultValue; 185 } 186 187 const item = JSON.parse(itemStr); 188 const now = new Date(); 189 190 // compare the expiry time of the item with the current time 191 if (now.getTime() > item.expiry) { 192 // If the item is expired, delete the item from storage 193 // and return null 194 localStorage.removeItem(prefixedKey); 195 return defaultValue; 196 } 197 return item.value; 198 } 199 200 201 export const handlingLocalStorageData = () => { 202 try { 203 let blockData = localStorage.getItem('block_data'); 204 if (!blockData || blockData == null) return; 205 blockData = JSON.parse(blockData); 206 if (!blockData || blockData == null || blockData.length < 1) return; 207 208 blockData = blockData.filter(block => (block.name && block.attributes && block.innerBlocks) ) 209 .map(block => { 210 if (block.name && block.attributes && block.innerBlocks) return createBlock(block.name, block.attributes, block.innerBlocks); 211 }); 212 if (blockData.length > 0) { 213 insertBlocks(blockData); 214 createSuccessNotice('Template inserted', {type: 'snackbar'}); 215 } 216 // preparing to call after import handling 217 let data = localStorage.getItem('importing_data'); 218 if (!data || data == null) return; 219 data = JSON.parse(data); 220 afterImportHandling(data, blockData); 221 222 // reset the localstorage 223 localStorage.setItem('block_data', null); 224 localStorage.setItem('importing_data', null); 225 } catch (error) { 226 alert(error.code + ' : ' + error.message); 227 } 228 } 229 230 231 export const columnMap = { 232 'large': 2, 233 'medium': 3, 234 'small': 4 235 }; 236 237 export const pageSizeMap = { 238 'large': 20, 239 'medium': 30, 240 'small': 40 241 }; 242 243 export const getOnlySelectedDependencyFilters = (dependencyFilters) => { 244 return Object.keys(dependencyFilters).filter(key => dependencyFilters[key]); 245 } 246 247 /* 248 Input: dependencies: {getwid: 38, qubely: 82...} 249 Input: dependencies: ['getwid', 'qubely', ...] 250 Result: {getwid: {value: true, disabled: true}, } 251 */ 252 export const getDefaultDependencies = (dependencies) => { 253 const unSupportedPlugins = Object.keys(redux_templates.supported_plugins).filter(key => isPluginProActivated(key) === false); 254 return dependencies.reduce( 255 (acc, cur) => { 256 // special handling for pro plugin not activated. 257 let value = true; 258 if (isProPlugin(cur) && (cur !== REDUXTEMPLATES_PRO_KEY) && isPluginReduxProMerged(cur) === false) value = false; // Not including pro plugin in redux templates 259 return {...acc, [cur]: {value, disabled: false}}; 260 }, 261 { 262 [NONE_KEY]: {value: true, disabled: false}, // Native element is included in default dependencies 263 [REDUXTEMPLATES_PRO_KEY]: {value: true, disabled: false} // Redux pro is included in default dependencies 264 } 265 ); 266 } 267 268 export const getInstalledDependencies = (dependencies) => { 269 const unSupportedPlugins = Object.keys(redux_templates.supported_plugins).filter(key => isPluginProActivated(key) === false); 270 return dependencies 271 .filter(key => key !== NONE_KEY) 272 .reduce( 273 (acc, cur) => { 274 // special handling for pro plugin not activated. 275 let value = true; 276 const pluginInstance = getPluginInstance(cur); 277 if (pluginInstance) { 278 if (isProPlugin(cur) && unSupportedPlugins.indexOf(cur) !== -1) value = false; 279 if (isProPlugin(cur) === false && pluginInstance.hasOwnProperty('version') === false) value = false; 280 if (cur === REDUXTEMPLATES_PRO_KEY) value = false; 281 } else 282 value = false; 283 return {...acc, [cur]: {value, disabled: false}}; 284 }, 285 { 286 [NONE_KEY]: {value: true, disabled: false} 287 } 288 ); 289 } 290 291 const isProPlugin = (pluginKey) => { 292 const pluginInstance = getPluginInstance(pluginKey); 293 return (pluginInstance && pluginInstance.hasOwnProperty('free_slug')); 294 } 295 296 const isPluginProActivated = (pluginKey) => { 297 const pluginInstance = getPluginInstance(pluginKey); 298 const freePluginInstance = getPluginInstance(pluginInstance.free_slug); 299 return (freePluginInstance.hasOwnProperty('version') && freePluginInstance.hasOwnProperty('is_pro') && freePluginInstance.is_pro !== false); 300 } 301 302 export const missingPluginsArray = () => { 303 return Object.keys(redux_templates.supported_plugins).filter(pluginKey => isProPlugin(pluginKey) && isPluginProActivated(pluginKey) === false); 304 } 305 306 307 308 /** 309 * Get last saved step. 310 */ 311 export const loadChallengeStep = () => { 312 var step = localStorage.getItem( 'reduxChallengeStep' ); 313 if (step === null) 314 return -1; 315 step = parseInt( step, 10 ); 316 return step; 317 } 318 319 /** 320 * Save Challenge step. 321 */ 322 export const saveChallengeStep = (step) => { 323 localStorage.setItem( 'reduxChallengeStep', step ); 324 } 325 326 327 const isThirdPartyPlugin = (pluginKey) => { 328 const pluginInstance = getPluginInstance(pluginKey); 329 return pluginInstance.free_slug && !pluginInstance.redux_pro && !pluginInstance.version; 330 }