diff --git a/app/src/app/admin/articles/article/article.ts b/app/src/app/admin/articles/article/article.ts index dee8a9d1..0bbfaa80 100644 --- a/app/src/app/admin/articles/article/article.ts +++ b/app/src/app/admin/articles/article/article.ts @@ -92,7 +92,7 @@ namespace app.admin.articles.article { */ public save(){ - return this.articleService.saveArticleWithRelated(this.article, this.$stateParams.newArticle) + return this.articleService.saveArticleWithRelated(this.article) .then(() => { this.notificationService.toast('Article saved').pop(); }); diff --git a/app/src/common/models/abstractModel.spec.ts b/app/src/common/models/abstractModel.spec.ts index 7bbdd8c3..2aa6f682 100644 --- a/app/src/common/models/abstractModel.spec.ts +++ b/app/src/common/models/abstractModel.spec.ts @@ -13,9 +13,9 @@ namespace common.models { public _hasOne:TestChildModel; public _hasMany:TestChildModel[]; - constructor(data:any) { - super(data); - this.hydrate(data); + constructor(data:any, exists:boolean = false) { + super(data, exists); + this.hydrate(data, exists); } } diff --git a/app/src/common/models/abstractModel.ts b/app/src/common/models/abstractModel.ts index 289d710a..88c493ac 100644 --- a/app/src/common/models/abstractModel.ts +++ b/app/src/common/models/abstractModel.ts @@ -6,7 +6,7 @@ namespace common.models { } export interface IModelFactory{ - (data:any):IModel; + (data:any, exists?:boolean):IModel; } export class AbstractModel implements IModel { @@ -14,26 +14,27 @@ namespace common.models { protected _nestedEntityMap; private _exists:boolean; - constructor(data?:any) { - this.hydrate(data); + constructor(data?:any, exists:boolean = false) { + this.hydrate(data, exists); Object.defineProperty(this, "_exists", { enumerable: false, writable: true, - value: false, + value: exists, }); } /** * Assign the properties of the model from the init data * @param data + * @param exists */ - protected hydrate(data?:any) { + protected hydrate(data:any, exists:boolean) { if (_.isObject(data)) { _.assign(this, data); if (_.size(this._nestedEntityMap) > 1) { - this.hydrateNested(data); + this.hydrateNested(data, exists); } } @@ -42,8 +43,9 @@ namespace common.models { /** * Find all the nested entities and hydrate them into model instances * @param data + * @param exists */ - protected hydrateNested(data:any){ + protected hydrateNested(data:any, exists:boolean){ _.forIn(this._nestedEntityMap, (model:typeof AbstractModel, nestedKey:string) => { @@ -51,9 +53,9 @@ namespace common.models { if (_.has(data, key) && !_.isNull(data[key])){ if (_.isArray(data[key])){ - this[key] = _.map(data[key], (entityData) => this.hydrateModel(entityData, model)); + this[key] = _.map(data[key], (entityData) => this.hydrateModel(entityData, model, exists)); }else if (_.isObject(data[key])){ - this[key] = this.hydrateModel(data[key], model); + this[key] = this.hydrateModel(data[key], model, exists); } }else{ @@ -68,12 +70,15 @@ namespace common.models { * Get a new instance of a model from data * @param data * @param Model - * @returns {undefined} + * @returns {common.models.AbstractModel} + * @param exists */ - private hydrateModel(data:any, Model:typeof AbstractModel){ + private hydrateModel(data:any, Model:typeof AbstractModel, exists:boolean){ - return new Model(data); + let model = new Model(data); + model.setExists(exists); + return model; } /** diff --git a/app/src/common/models/article/articleModel.ts b/app/src/common/models/article/articleModel.ts index b7db5efc..ef132ece 100644 --- a/app/src/common/models/article/articleModel.ts +++ b/app/src/common/models/article/articleModel.ts @@ -16,9 +16,9 @@ namespace common.models { public _tags:common.models.Tag[]; - constructor(data:any) { - super(data); - this.hydrate(data); + constructor(data:any, exists:boolean = false) { + super(data, exists); + this.hydrate(data, exists); } /** diff --git a/app/src/common/models/tag/tagModel.ts b/app/src/common/models/tag/tagModel.ts index cd89a370..b9c0325b 100644 --- a/app/src/common/models/tag/tagModel.ts +++ b/app/src/common/models/tag/tagModel.ts @@ -6,9 +6,9 @@ namespace common.models { public tagId:string = undefined; public tag:string = undefined; - constructor(data:any) { - super(data); - this.hydrate(data); + constructor(data:any, exists:boolean = false) { + super(data, exists); + this.hydrate(data, exists); } } diff --git a/app/src/common/models/user/userModel.ts b/app/src/common/models/user/userModel.ts index 00670e93..09d605d3 100644 --- a/app/src/common/models/user/userModel.ts +++ b/app/src/common/models/user/userModel.ts @@ -20,9 +20,9 @@ namespace common.models { public _socialLogins:common.models.UserSocialLogin[] = undefined; public userType:string = undefined; - constructor(data:any) { - super(data); - this.hydrate(data); + constructor(data:any, exists:boolean = false) { + super(data, exists); + this.hydrate(data, exists); } /** diff --git a/app/src/common/models/user/userProfileModel.ts b/app/src/common/models/user/userProfileModel.ts index 30a5bca6..adb6a520 100644 --- a/app/src/common/models/user/userProfileModel.ts +++ b/app/src/common/models/user/userProfileModel.ts @@ -23,9 +23,9 @@ module common.models { {label: 'Prefer not to say', value: 'N/A'} ]; - constructor(data:any) { - super(data); - this.hydrate(data); + constructor(data:any, exists:boolean = false) { + super(data, exists); + this.hydrate(data, exists); } } diff --git a/app/src/common/models/user/userSocialLoginModel.ts b/app/src/common/models/user/userSocialLoginModel.ts index b81105cb..6df4a772 100644 --- a/app/src/common/models/user/userSocialLoginModel.ts +++ b/app/src/common/models/user/userSocialLoginModel.ts @@ -10,9 +10,9 @@ module common.models { public provider:string = undefined; public token:string = undefined; - constructor(data:any) { - super(data); - this.hydrate(data); + constructor(data:any, exists:boolean = false) { + super(data, exists); + this.hydrate(data, exists); } } diff --git a/app/src/common/services/article/articleService.spec.ts b/app/src/common/services/article/articleService.spec.ts index 17e3f167..b6a10301 100644 --- a/app/src/common/services/article/articleService.spec.ts +++ b/app/src/common/services/article/articleService.spec.ts @@ -141,7 +141,7 @@ $httpBackend.expectPUT('/api/articles/'+article.articleId, article.getAttributes()).respond(201); $httpBackend.expectPUT('/api/articles/'+article.articleId+'/tags', _.clone(article._tags, true)).respond(201); - let savePromise = articleService.saveArticleWithRelated(article, true); + let savePromise = articleService.saveArticleWithRelated(article); expect(savePromise).eventually.to.be.fulfilled; expect(savePromise).eventually.to.deep.equal(article); diff --git a/app/src/common/services/article/articleService.ts b/app/src/common/services/article/articleService.ts index 6285d6cd..c83c3b43 100644 --- a/app/src/common/services/article/articleService.ts +++ b/app/src/common/services/article/articleService.ts @@ -15,9 +15,10 @@ namespace common.services.article { * Get an instance of the Article given data * @param data * @returns {common.models.Article} + * @param exists */ - public static articleFactory(data:any):common.models.Article { - return new common.models.Article(data); + public static articleFactory(data:any, exists:boolean = false):common.models.Article { + return new common.models.Article(data, exists); } /** @@ -65,16 +66,15 @@ namespace common.services.article { /** * Save the article with all the nested entities too * @param article - * @param newArticle * @returns {IPromise} */ - public saveArticleWithRelated(article:common.models.Article, newArticle:boolean = false):ng.IPromise{ + public saveArticleWithRelated(article:common.models.Article):ng.IPromise{ - - return this.saveArticle(article, newArticle) - .then(() => this.saveRelatedEntities(article, newArticle)) + return this.saveArticle(article) + .then(() => this.saveRelatedEntities(article)) .then(() => { (article).resetChangedProperties(); //reset so next save only saves the changed ones + article.setExists(true); return article; }) ; @@ -84,16 +84,15 @@ namespace common.services.article { /** * Save the article * @param article - * @param newArticle * @returns ng.IPromise */ - public saveArticle(article:common.models.Article, newArticle:boolean = false):ng.IPromise{ + public saveArticle(article:common.models.Article):ng.IPromise{ - let method = newArticle ? 'put' : 'patch'; + let method = article.exists() ? 'patch' : 'put'; let saveData = article.getAttributes(); - if (!newArticle) { + if (article.exists()) { saveData = (article).getChanged(); } @@ -111,10 +110,10 @@ namespace common.services.article { * @param article * @returns {IPromise} */ - private saveRelatedEntities(article:common.models.Article, newArticle:boolean = false):ng.IPromise { + private saveRelatedEntities(article:common.models.Article):ng.IPromise { return this.$q.all([ //save all related entities - this.saveArticleTags(article, newArticle), + this.saveArticleTags(article), ]); } @@ -124,11 +123,11 @@ namespace common.services.article { * @param article * @returns {any} */ - private saveArticleTags(article:common.models.Article, newArticle:boolean = false):ng.IPromise{ + private saveArticleTags(article:common.models.Article):ng.IPromise{ let tagData = _.clone(article._tags); - if (!newArticle){ + if (article.exists()){ let changes:any = (article).getChanged(true); if (!_.has(changes, '_tags')){ @@ -138,7 +137,6 @@ namespace common.services.article { return this.ngRestAdapter.put('/articles/'+article.articleId+'/tags', tagData) .then(() => { - console.log('tags saved'); return article._tags; }); diff --git a/app/src/common/services/auth/authService.ts b/app/src/common/services/auth/authService.ts index 33489b56..1032c129 100644 --- a/app/src/common/services/auth/authService.ts +++ b/app/src/common/services/auth/authService.ts @@ -40,7 +40,7 @@ namespace common.services.auth { return this.ngJwtAuthService .registerUserFactory((subClaim: string, tokenData: global.JwtAuthClaims): ng.IPromise => { - return this.$q.when(new common.models.User(tokenData._user)); + return this.$q.when(new common.models.User(tokenData._user, true)); }) .registerLoginPromptFactory((deferredCredentials:ng.IDeferred, loginSuccessPromise:ng.IPromise, currentUser:NgJwtAuth.IUser): ng.IPromise => { diff --git a/app/src/common/services/pagination/paginationService.ts b/app/src/common/services/pagination/paginationService.ts index 3cad6e6c..b0fb7ca9 100644 --- a/app/src/common/services/pagination/paginationService.ts +++ b/app/src/common/services/pagination/paginationService.ts @@ -27,7 +27,7 @@ namespace common.services.pagination { private $q:ng.IQService, private $window:ng.IWindowService) { - this.modelFactory = (data:any) => data; //set a default factory that just returns the data + this.modelFactory = (data:any, exists:boolean) => data; //set a default factory that just returns the data } @@ -83,7 +83,7 @@ namespace common.services.pagination { Range: Paginator.getRangeHeader(index, last) }).then((response:ng.IHttpPromiseCallbackArg) => { this.processContentRangeHeader(response.headers); - return _.map(response.data, (modelData) => this.modelFactory(modelData)); + return _.map(response.data, (modelData) => this.modelFactory(modelData, true)); }).catch((response:ng.IHttpPromiseCallbackArg) => { if(response.status == 404){ //no content this.entityCountTotal = 0; diff --git a/app/src/common/services/tag/tagService.ts b/app/src/common/services/tag/tagService.ts index a70b39f6..04ac10da 100644 --- a/app/src/common/services/tag/tagService.ts +++ b/app/src/common/services/tag/tagService.ts @@ -16,9 +16,10 @@ namespace common.services.tag { * Get an instance of the Tag given data * @param data * @returns {common.models.Tag} + * @param exists */ - public static tagFactory(data:any):common.models.Tag { - return new common.models.Tag(data); + public static tagFactory(data:any, exists:boolean = false):common.models.Tag { + return new common.models.Tag(data, exists); } /** diff --git a/app/src/common/services/user/userService.spec.ts b/app/src/common/services/user/userService.spec.ts index 7dd0d6cf..8a2652b3 100644 --- a/app/src/common/services/user/userService.spec.ts +++ b/app/src/common/services/user/userService.spec.ts @@ -290,7 +290,7 @@ it('should be able to send a patch request to update the user details (including profile)', () => { - let user = _.clone(fixtures.user); + let user = fixtures.user; let profile = _.clone(userProfile); diff --git a/app/src/common/services/user/userService.ts b/app/src/common/services/user/userService.ts index 4b3ff572..d8f91811 100644 --- a/app/src/common/services/user/userService.ts +++ b/app/src/common/services/user/userService.ts @@ -20,10 +20,11 @@ namespace common.services.user { /** * Get an instance of a user from data * @param userData - * @returns {common.services.user.User} + * @returns {common.models.User} + * @param exists */ - public static userFactory(userData:global.IUserData):common.models.User { - return new common.models.User(userData); + public static userFactory(userData:global.IUserData, exists:boolean = false):common.models.User { + return new common.models.User(userData, exists); } /** @@ -66,7 +67,10 @@ namespace common.services.user { let user = new common.models.User(userData); return this.ngRestAdapter.put('/users/' + user.userId, user) - .then(() => user); //return this user object + .then(() => { + user.setExists(true); + return user; + }); //return this user object } /** @@ -148,20 +152,20 @@ namespace common.services.user { */ public updateUser(user:common.models.User):ng.IPromise { return this.ngRestAdapter - .patch('/users/' + user.userId, user); + .patch('/users/' + user.userId, user.getAttributes(true)); } /** * Get full user information * @param user - * @returns {ng.IHttpPromise} + * @returns {ng.IPromise} */ public getUser(user:common.models.User):ng.IPromise { return this.ngRestAdapter.get('/users/' + user.userId, { 'With-Nested' : 'userCredential, userProfile, socialLogins' }) .then((res) => { - return new common.models.User(res.data); + return new common.models.User(res.data, true); }); }