Faster module loading & vnAgencyCalendar bug fixes
This commit is contained in:
parent
4fcaa2e507
commit
026c608f42
|
@ -94,7 +94,7 @@ describe('Component vnDialog', () => {
|
|||
expect(controller.onAccept).toHaveBeenCalledWith({$response: 'accept'});
|
||||
});
|
||||
|
||||
it(`should resolve the promise returned by show() with response`, () => {
|
||||
it(`should resolve the promise returned by show() with response when hidden`, () => {
|
||||
let response;
|
||||
controller.show().then(res => response = res);
|
||||
controller.respond('response');
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
import isEqual from './equals';
|
||||
|
||||
export default function getModifiedData(object, objectOld) {
|
||||
var newObject = {};
|
||||
let newObject = {};
|
||||
if (objectOld === null)
|
||||
return object;
|
||||
|
||||
for (var k in object) {
|
||||
var val = object[k];
|
||||
var valOld = objectOld[k] === undefined ? null : objectOld[k];
|
||||
for (let k in object) {
|
||||
let val = object[k];
|
||||
let valOld = objectOld[k] === undefined ? null : objectOld[k];
|
||||
|
||||
if (!isEqual(val, valOld)) {
|
||||
if (val instanceof Date) {
|
||||
if (val instanceof Date)
|
||||
newObject[k] = new Date(val.getTime());
|
||||
} else if (val instanceof Object) {
|
||||
else if (val instanceof Object)
|
||||
newObject[k] = getModifiedData(val, valOld);
|
||||
} else {
|
||||
else
|
||||
newObject[k] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Object.keys(newObject).length ? newObject : undefined;
|
||||
}
|
||||
|
|
|
@ -3,64 +3,80 @@ import moduleImport from 'module-import';
|
|||
|
||||
factory.$inject = ['$http', '$window', '$ocLazyLoad', '$translatePartialLoader', '$translate', '$q'];
|
||||
export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $translate, $q) {
|
||||
/**
|
||||
* Used to load application modules lazily.
|
||||
*/
|
||||
class ModuleLoader {
|
||||
constructor() {
|
||||
this._loaded = {};
|
||||
this.loaded = {};
|
||||
this.imports = {};
|
||||
this.moduleImport = moduleImport;
|
||||
this.modelInfo = $http.get(`modelInfo`)
|
||||
.then(json => {
|
||||
this.onModelInfoReady(json);
|
||||
this.modelInfo = true;
|
||||
});
|
||||
}
|
||||
load(moduleName, validations) {
|
||||
let moduleConf = $window.routes.find(i => i && i.module == moduleName);
|
||||
|
||||
/**
|
||||
* Loads the passed module and it's dependencies. Loading a module
|
||||
* implies load the webpack chunk, translations, recursively load
|
||||
* module dependencies and finally register all of them into Angular.
|
||||
*
|
||||
* @param {String} mod The module name to load
|
||||
* @return {Promise} Will be resolved when loaded, when module is
|
||||
* already loaded it returns a resolved promise
|
||||
*/
|
||||
load(mod) {
|
||||
let mods = [];
|
||||
return this.loadRec(mod, mods);
|
||||
}
|
||||
|
||||
loadRec(mod, mods) {
|
||||
let loaded = this.loaded[mod];
|
||||
|
||||
if (loaded === true || mods.indexOf(mod) != -1)
|
||||
return $q.resolve(true);
|
||||
if (loaded instanceof $q)
|
||||
return loaded;
|
||||
|
||||
let moduleConf = $window.routes.find(i => i && i.module == mod);
|
||||
if (!moduleConf)
|
||||
return $q.reject(new Error(`Module not found: ${moduleName}`));
|
||||
return $q.reject(new Error(`Module not found: ${mod}`));
|
||||
|
||||
let loaded = this._loaded;
|
||||
let promises = [];
|
||||
|
||||
if (loaded[moduleName] === true)
|
||||
return Promise.resolve(true);
|
||||
if (loaded[moduleName] instanceof Promise)
|
||||
return loaded[moduleName];
|
||||
if (loaded[moduleName] === false)
|
||||
return Promise.resolve(true);
|
||||
if (this.modelInfo instanceof $q)
|
||||
promises.push(this.modelInfo);
|
||||
|
||||
loaded[moduleName] = false;
|
||||
$translatePartialLoader.addPart(mod);
|
||||
promises.push($translate.refresh());
|
||||
|
||||
let modImport = this.imports[mod];
|
||||
|
||||
if (!modImport) {
|
||||
modImport = this.imports[mod] = this.moduleImport(mod)
|
||||
.then(() => this.imports[mod] = true);
|
||||
}
|
||||
if (modImport && modImport.then)
|
||||
promises.push(modImport);
|
||||
|
||||
let depPromises = [];
|
||||
let deps = moduleConf.dependencies;
|
||||
|
||||
if (deps) {
|
||||
mods.push(mod);
|
||||
for (let dep of deps)
|
||||
depPromises.push(this.load(dep, validations));
|
||||
promises.push(this.loadRec(dep, mods));
|
||||
mods.pop();
|
||||
}
|
||||
|
||||
loaded[moduleName] = new Promise((resolve, reject) => {
|
||||
Promise.all(depPromises).then(() => {
|
||||
let promises = [];
|
||||
|
||||
$translatePartialLoader.addPart(moduleName);
|
||||
promises.push(new Promise(resolve => {
|
||||
$translate.refresh().then(resolve, resolve);
|
||||
}));
|
||||
|
||||
if (validations) {
|
||||
promises.push(new Promise(resolve => {
|
||||
$http.get(`/${moduleName}/api/modelInfo`).then(
|
||||
json => this.onValidationsReady(json, resolve),
|
||||
() => resolve()
|
||||
);
|
||||
}));
|
||||
this.loaded[mod] = $q.all(promises)
|
||||
.then(() => $ocLazyLoad.load({name: mod}))
|
||||
.then(() => this.loaded[mod] = true);
|
||||
return this.loaded[mod];
|
||||
}
|
||||
|
||||
promises.push(moduleImport(moduleName));
|
||||
|
||||
Promise.all(promises).then(() => {
|
||||
loaded[moduleName] = true;
|
||||
resolve($ocLazyLoad.load({name: moduleName}));
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
});
|
||||
|
||||
return loaded[moduleName];
|
||||
}
|
||||
onValidationsReady(json, resolve) {
|
||||
onModelInfoReady(json) {
|
||||
let entities = json.data;
|
||||
for (let entity in entities) {
|
||||
let fields = entities[entity].validations;
|
||||
|
@ -72,12 +88,13 @@ export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $t
|
|||
}
|
||||
|
||||
Object.assign($window.validations, json.data);
|
||||
resolve();
|
||||
}
|
||||
|
||||
parseValidation(val) {
|
||||
switch (val.validation) {
|
||||
case 'custom':
|
||||
// TODO: Replace eval
|
||||
// TODO: Don't use eval() because it's "evil".
|
||||
// How to do the same without eval?
|
||||
val.bindedFunction = eval(`(${val.bindedFunction})`);
|
||||
break;
|
||||
case 'format':
|
||||
|
|
|
@ -1,30 +1,108 @@
|
|||
describe('factory vnModuleLoader', () => {
|
||||
let vnModuleLoader;
|
||||
let $rootScope;
|
||||
let $window;
|
||||
|
||||
beforeEach(ngModule('vnCore'));
|
||||
|
||||
beforeEach(angular.mock.inject((_vnModuleLoader_, $rootScope, $window) => {
|
||||
beforeEach(angular.mock.inject((_vnModuleLoader_, _$rootScope_, $httpBackend, _$window_, $q) => {
|
||||
vnModuleLoader = _vnModuleLoader_;
|
||||
$window.routes = [{module: 'myModule'}];
|
||||
$rootScope = _$rootScope_;
|
||||
$window = _$window_;
|
||||
|
||||
$window.validations = {};
|
||||
$window.routes = [
|
||||
{
|
||||
module: 'myModule',
|
||||
dependencies: ['fooModule', 'barModule']
|
||||
}, {
|
||||
module: 'fooModule',
|
||||
dependencies: ['myModule']
|
||||
}, {
|
||||
module: 'barModule'
|
||||
}
|
||||
];
|
||||
|
||||
$httpBackend.whenGET('modelInfo')
|
||||
.respond({
|
||||
FooModel: {
|
||||
properties: {
|
||||
id: {type: 'Number'},
|
||||
email: {type: 'String'},
|
||||
field: {type: 'Boolean'}
|
||||
},
|
||||
validations: {
|
||||
id: [{
|
||||
validation: 'presence'
|
||||
}],
|
||||
email: [{
|
||||
validation: 'format',
|
||||
with: '/@/'
|
||||
}],
|
||||
field: [{
|
||||
validation: 'custom',
|
||||
bindedFunction: '() => true'
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
$httpBackend.flush();
|
||||
|
||||
vnModuleLoader.moduleImport = () => $q.resolve();
|
||||
}));
|
||||
|
||||
describe('load()', () => {
|
||||
it('should return truthy promise if the module was loaded', async() => {
|
||||
vnModuleLoader._loaded.myModule = true;
|
||||
it('should throw error if module does not exist', async() => {
|
||||
let errorThrown;
|
||||
|
||||
let result = await vnModuleLoader.load('myModule', {myValidations: () => {}});
|
||||
vnModuleLoader.load('unexistentModule')
|
||||
.catch(() => errorThrown = true);
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(result).toEqual(true);
|
||||
expect(errorThrown).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return a promise if the module was still a promise', () => {
|
||||
vnModuleLoader._loaded.myModule = new Promise(() => {
|
||||
return 'I promise you a module!';
|
||||
it('should set module loaded to true when it is loaded', async() => {
|
||||
vnModuleLoader.load('barModule');
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(vnModuleLoader.loaded['barModule']).toBeTruthy();
|
||||
});
|
||||
|
||||
let result = vnModuleLoader.load('myModule', {myValidations: () => {}});
|
||||
it('should resolve returned promise when module is loaded', async() => {
|
||||
let loaded;
|
||||
|
||||
expect(result).toEqual(jasmine.any(Promise));
|
||||
vnModuleLoader.load('barModule')
|
||||
.then(() => loaded = true);
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(loaded).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should load dependencies', async() => {
|
||||
vnModuleLoader.load('fooModule');
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(vnModuleLoader.loaded['barModule']).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should work with circular dependencies', async() => {
|
||||
vnModuleLoader.load('myModule');
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(vnModuleLoader.loaded['fooModule']).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should load models information and parse validations', async() => {
|
||||
vnModuleLoader.load('barModule');
|
||||
|
||||
let FooModel = $window.validations.FooModel;
|
||||
let validations = FooModel && FooModel.validations;
|
||||
|
||||
expect(FooModel).toBeDefined();
|
||||
expect(validations).toBeDefined();
|
||||
expect(validations.email[0].with).toBeInstanceOf(RegExp);
|
||||
expect(validations.field[0].bindedFunction).toBeInstanceOf(Function);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,9 +8,11 @@ export default class Modules {
|
|||
$window
|
||||
});
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.modules = null;
|
||||
}
|
||||
|
||||
get() {
|
||||
if (this.modules)
|
||||
return this.modules;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import ngModule from './module';
|
||||
import getMainRoute from 'core/lib/get-main-route';
|
||||
|
||||
function loader(moduleName, validations) {
|
||||
function loader(moduleName) {
|
||||
load.$inject = ['vnModuleLoader'];
|
||||
function load(moduleLoader) {
|
||||
return moduleLoader.load(moduleName, validations);
|
||||
return moduleLoader.load(moduleName);
|
||||
}
|
||||
return load;
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ function config($stateProvider, $urlRouterProvider) {
|
|||
if (!route.params)
|
||||
return params;
|
||||
|
||||
|
||||
Object.keys(route.params).forEach(key => {
|
||||
temporalParams.push(`${key} = "${route.params[key]}"`);
|
||||
});
|
||||
|
|
|
@ -91,7 +91,7 @@ class Controller extends Component {
|
|||
this.days = {};
|
||||
let day = new Date(this.firstDay.getTime());
|
||||
|
||||
while (day < this.lastDay) {
|
||||
while (day <= this.lastDay) {
|
||||
let stamp = day.getTime();
|
||||
let wday = day.getDay();
|
||||
let dayEvents = [];
|
||||
|
|
Loading…
Reference in New Issue