From 7e523f878228cdcdd1754781accb5d998449a8ad Mon Sep 17 00:00:00 2001 From: Lajos Date: Fri, 1 Dec 2017 11:35:11 +0100 Subject: [PATCH 1/5] Feature/codepen docs (#80) * [KFI]docs(authentication): added codepen snippet * [KFI]docs(Content): added codepen snippet * [KFI]docs(Query): added CodePen snippet --- src/Authentication/index.ts | 2 ++ src/Content/index.ts | 5 +++-- src/Query/index.ts | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Authentication/index.ts b/src/Authentication/index.ts index 2ca99e0..f7a7d9f 100644 --- a/src/Authentication/index.ts +++ b/src/Authentication/index.ts @@ -2,6 +2,8 @@ * @module Authentication * @preferred * @description This module that contains authentication-related classes, types and interfaces + * + *

See the Pen @sensenet/sn-client-js/login by gallayl (@gallayl) on CodePen.

*/ /** */ export * from './IAuthenticationService'; diff --git a/src/Content/index.ts b/src/Content/index.ts index d9ff8d3..0d0efd0 100644 --- a/src/Content/index.ts +++ b/src/Content/index.ts @@ -2,10 +2,11 @@ * @module Content * @preferred * - * @description Top level base type of sense NET's Type hierarchy. - * + * @description Top level base type of sense NET's Type hierarchy. Content has the basic properties and functionality that can be reached on all of the inherited types. It's almost the same as an abstract class, it may not be instantiated directly, + * but it has the basic methods implemented that can be called on obejcts with derived types. Unlike other Content Types it is not autogenerated. * Content has the basic properties and functionality that can be reached on all of the inherited types. It's almost the same as an abstract class, it may not be instantiated directly, * but it has the basic methods implemented that can be called on obejcts with derived types. + *

See the Pen @sensenet/sn-client-js/content by gallayl (@gallayl) on CodePen.

* * Unlike other Content Types it is not autogenerated. * diff --git a/src/Query/index.ts b/src/Query/index.ts index 3aaf028..2246076 100644 --- a/src/Query/index.ts +++ b/src/Query/index.ts @@ -3,6 +3,8 @@ * @preferred * * @description Classes and Methods for creating, manipulating and executing content queries in sensenet ECM. + * + *

See the Pen @sensenet/sn-client-js/query by gallayl (@gallayl) on CodePen.

*/ /** */ export * from './Query'; From 11c50d7446b7c74d94f6f5eab0b3ed05fb903112 Mon Sep 17 00:00:00 2001 From: Lajos Date: Tue, 5 Dec 2017 10:52:51 +0100 Subject: [PATCH 2/5] Hotfix/reference fields (#81) * chore(package): update @types/chai to version 4.0.5 (#78) * chore(package): update tslint-consistent-codestyle to version 1.10.2 (#79) * [KFI]fix(Content Reference and List Fields): fixed reference loading when no _deferred object has be --- package.json | 4 ++-- src/Content/ContentInternal.ts | 2 +- src/ContentReferences.ts | 14 ++++++++---- test/ContentListReferenceFieldTests.ts | 7 ++++-- test/ContentReferenceFieldTests.ts | 8 +++++-- test/ContentTests.ts | 30 +++++++++++++------------- 6 files changed, 39 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index c69002c..11a28f7 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ }, "devDependencies": { "@types/app-root-path": "1.2.4", - "@types/chai": "4.0.4", + "@types/chai": "4.0.5", "@types/mocha": "2.2.44", "@types/node": "^8.0.0", "chai": "4.1.2", @@ -75,7 +75,7 @@ "mocha-typescript": "^1.0.23", "rimraf": "^2.6.1", "tslint": "^5.8.0", - "tslint-consistent-codestyle": "^1.9.0", + "tslint-consistent-codestyle": "^1.10.2", "typedoc": "^0.9.0", "typedoc-plugin-external-module-name": "^1.0.9", "typescript": "^2.6.1" diff --git a/src/Content/ContentInternal.ts b/src/Content/ContentInternal.ts index c43cc4d..73ce4ec 100644 --- a/src/Content/ContentInternal.ts +++ b/src/Content/ContentInternal.ts @@ -167,7 +167,7 @@ referenceSettings.forEach((f) => { if (!this._fieldHandlerCache[f.Name]) { - this._fieldHandlerCache[f.Name] = f.AllowMultiple ? new ContentListReferenceField(this[f.Name], f, this._repository) : new ContentReferenceField(this[f.Name], f, this._repository); + this._fieldHandlerCache[f.Name] = f.AllowMultiple ? new ContentListReferenceField(this[f.Name], f, this, this._repository) : new ContentReferenceField(this[f.Name], f, this, this._repository); } else { this._fieldHandlerCache[f.Name].HandleLoaded(this[f.Name]); } diff --git a/src/ContentReferences.ts b/src/ContentReferences.ts index 3e97eec..edcdb94 100644 --- a/src/ContentReferences.ts +++ b/src/ContentReferences.ts @@ -7,6 +7,7 @@ import { DeferredObject } from './ComplexTypes'; import { IContent, isDeferred, isIContent, SavedContent } from './Content'; import { ReferenceFieldSetting } from './FieldSettings'; import { IODataParams } from './ODataApi/ODataParams'; +import { joinPaths } from './ODataHelper'; import { FinializedQuery } from './Query'; import { BaseRepository } from './Repository/BaseRepository'; import { ContentTypes, isIContentList } from './SN'; @@ -101,10 +102,12 @@ export class ContentReferenceField extends ReferenceAbstract * @returns {Observable} An observable that will publish the referenced content */ public GetContent(odataOptions?: IODataParams): Observable> { - if (this._contentReference !== undefined) { + if (!this._ownerContent.IsSaved || this._contentReference !== undefined) { return Observable.of(this._contentReference); } - const request = this.Repository.GetODataApi().Get({ path: this._referenceUrl, params: odataOptions }) + const request = this.Repository.GetODataApi().Get({ + path: this._referenceUrl || joinPaths(this._ownerContent.GetFullPath(), this.FieldSetting.Name), + params: odataOptions }) .map((r) => { return r && r.d && this.Repository.HandleLoadedContent(r.d); }).share(); @@ -137,6 +140,7 @@ export class ContentReferenceField extends ReferenceAbstract constructor(fieldData: DeferredObject | SavedContent, public readonly FieldSetting: ReferenceFieldSetting, + private readonly _ownerContent: SavedContent, public readonly Repository: BaseRepository) { super(); this.HandleLoaded(fieldData); @@ -174,12 +178,12 @@ export class ContentListReferenceField extends ReferenceAbst * @returns {Observable} An observable that will publish the list of the referenced content */ public GetContent(odataOptions?: IODataParams): Observable[]> { - if (this._contentReferences) { + if (!this._ownerContent.IsSaved || this._contentReferences) { return Observable.of(this._contentReferences); } // const request = this.Repository.GetODataApi().Fetch({ - path: this._referenceUrl, + path: this._referenceUrl || joinPaths(this._ownerContent.GetFullPath(), this.FieldSetting.Name), params: odataOptions }).map((resp) => { return resp && resp.d && resp.d.results.map((c) => this.Repository.HandleLoadedContent(c)) || []; @@ -217,6 +221,8 @@ export class ContentListReferenceField extends ReferenceAbst constructor(fieldData: DeferredObject | T[], public readonly FieldSetting: ReferenceFieldSetting, + private readonly _ownerContent: SavedContent, + public readonly Repository: BaseRepository) { super(); this.HandleLoaded(fieldData); diff --git a/test/ContentListReferenceFieldTests.ts b/test/ContentListReferenceFieldTests.ts index e7bca7a..1329947 100644 --- a/test/ContentListReferenceFieldTests.ts +++ b/test/ContentListReferenceFieldTests.ts @@ -17,10 +17,13 @@ export class ContentListReferenceFieldTests { private _unloadedRef: ContentListReferenceField; private _loadedRef: ContentListReferenceField; + private _ownerContent: Task; + private _repo: MockRepository; // tslint:disable-next-line:naming-convention public before() { this._repo = new MockRepository(); + this._ownerContent = this._repo.HandleLoadedContent({Id: 123765, Path: 'Root/Tests', Name: 'TestOwnerContent'}, Task); this._repo.Authentication.StateSubject.next(LoginState.Authenticated); this._loadedRef = new ContentListReferenceField( [{ @@ -29,12 +32,12 @@ export class ContentListReferenceFieldTests { Name: 'Name', Type: 'Task', DueText: 'testDueText' - } as Task], {} as ReferenceFieldSetting, this._repo); + } as Task], {} as ReferenceFieldSetting, this._ownerContent, this._repo); this._unloadedRef = new ContentListReferenceField({ __deferred: { uri: 'a/b/c' } - } as DeferredObject, {} as ReferenceFieldSetting, this._repo); + } as DeferredObject, {} as ReferenceFieldSetting, this._ownerContent, this._repo); } @test diff --git a/test/ContentReferenceFieldTests.ts b/test/ContentReferenceFieldTests.ts index 4ab33f8..0b6591b 100644 --- a/test/ContentReferenceFieldTests.ts +++ b/test/ContentReferenceFieldTests.ts @@ -18,10 +18,14 @@ export class ContentReferenceFieldTests { private _loadedRef: ContentReferenceField; private _repo: MockRepository; + + private _ownerContent: Task; + // tslint:disable-next-line:naming-convention public before() { this._repo = new MockRepository(); this._repo.Authentication.StateSubject.next(LoginState.Authenticated); + this._ownerContent = this._repo.HandleLoadedContent({Id: 123765, Path: 'Root/Tests', Name: 'TestOwnerContent'}, Task); this._loadedRef = new ContentReferenceField(this._repo.HandleLoadedContent({ Id: 1, @@ -29,12 +33,12 @@ export class ContentReferenceFieldTests { Name: 'Name', Type: 'Task', DueText: 'testDueText' - }), {} as ReferenceFieldSetting, this._repo); + }), {} as ReferenceFieldSetting, this._ownerContent, this._repo); this._unloadedRef = new ContentReferenceField({ __deferred: { uri: 'a/b/c' } - } as DeferredObject, {} as ReferenceFieldSetting, this._repo); + } as DeferredObject, {} as ReferenceFieldSetting, this._ownerContent, this._repo); } @test diff --git a/test/ContentTests.ts b/test/ContentTests.ts index fda072d..0851eeb 100644 --- a/test/ContentTests.ts +++ b/test/ContentTests.ts @@ -625,7 +625,7 @@ export const contentTests = describe('Content', () => { }); }); it('should return an Observable object', () => { - expect(content.GetAllowedChildTypes({ select: ['Name'] })).to.be.instanceof(Observable); + expect(contentSaved.GetAllowedChildTypes({ select: ['Name'] })).to.be.instanceof(Observable); }); }); describe('#GetEffectiveAllowedChildTypes()', () => { @@ -638,51 +638,51 @@ export const contentTests = describe('Content', () => { }); describe('#GetOwner()', () => { it('should return an Observable object', () => { - expect(content.GetOwner()).to.be.instanceof(Observable); + expect(contentSaved.GetOwner()).to.be.instanceof(Observable); }); }); describe('#GetOwner()', () => { it('should return an Observable object', () => { - expect(content.GetOwner({ select: ['Name'] })).to.be.instanceof(Observable); + expect(contentSaved.GetOwner({ select: ['Name'] })).to.be.instanceof(Observable); }); }); describe('#Creator()', () => { it('should return an Observable object', () => { - expect(content.Creator()).to.be.instanceof(Observable); + expect(contentSaved.Creator()).to.be.instanceof(Observable); }); }); describe('#Creator()', () => { it('should return an Observable object', () => { - expect(content.Creator({ select: ['Name'] })).to.be.instanceof(Observable); + expect(contentSaved.Creator({ select: ['Name'] })).to.be.instanceof(Observable); }); }); describe('#Modifier()', () => { it('should return an Observable object', () => { - expect(content.Modifier()).to.be.instanceof(Observable); + expect(contentSaved.Modifier()).to.be.instanceof(Observable); }); }); describe('#Modifier()', () => { it('should return an Observable object', () => { - expect(content.Modifier({ select: ['Name'] })).to.be.instanceof(Observable); + expect(contentSaved.Modifier({ select: ['Name'] })).to.be.instanceof(Observable); }); }); describe('#CheckedOutBy()', () => { it('should return an Observable object', () => { - expect(content.CheckedOutBy()).to.be.instanceof(Observable); + expect(contentSaved.CheckedOutBy()).to.be.instanceof(Observable); }); }); describe('#CheckedOutBy()', () => { it('should return an Observable object', () => { - expect(content.CheckedOutBy({ select: ['Name'] })).to.be.instanceof(Observable); + expect(contentSaved.CheckedOutBy({ select: ['Name'] })).to.be.instanceof(Observable); }); }); describe('#Children()', () => { it('should return an Observable object', () => { - expect(content.Children()).to.be.instanceof(Observable); + expect(contentSaved.Children()).to.be.instanceof(Observable); }); it('should return an Observable object', () => { - expect(content.Children({ select: ['Name'] })).to.be.instanceof(Observable); + expect(contentSaved.Children({ select: ['Name'] })).to.be.instanceof(Observable); }); it('should throw error if no path provided', () => { @@ -712,22 +712,22 @@ export const contentTests = describe('Content', () => { }); describe('#Versions()', () => { it('should return an Observable object', () => { - expect(content.GetVersions()).to.be.instanceof(Observable); + expect(contentSaved.GetVersions()).to.be.instanceof(Observable); }); }); describe('#Versions()', () => { it('should return an Observable object', () => { - expect(content.GetVersions({ select: ['Name'] })).to.be.instanceof(Observable); + expect(contentSaved.GetVersions({ select: ['Name'] })).to.be.instanceof(Observable); }); }); describe('#Workspace()', () => { it('should return an Observable object', () => { - expect(content.GetWorkspace()).to.be.instanceof(Observable); + expect(contentSaved.GetWorkspace()).to.be.instanceof(Observable); }); }); describe('#Workspace()', () => { it('should return an Observable object', () => { - expect(content.GetWorkspace({ select: ['Name'] })).to.be.instanceof(Observable); + expect(contentSaved.GetWorkspace({ select: ['Name'] })).to.be.instanceof(Observable); }); }); describe('#Checkout()', () => { From 93949840391e2496186f803f5acf542012516e79 Mon Sep 17 00:00:00 2001 From: Lajos Date: Tue, 5 Dec 2017 11:06:27 +0100 Subject: [PATCH 3/5] [KFI]refactor(Content): renamed Actions() to GetActions(). Actions() marked as deprecated (#85) --- src/Content/ContentInternal.ts | 10 ++++++++-- test/ContentTests.ts | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Content/ContentInternal.ts b/src/Content/ContentInternal.ts index 73ce4ec..8ff2ead 100644 --- a/src/Content/ContentInternal.ts +++ b/src/Content/ContentInternal.ts @@ -467,14 +467,20 @@ * @param {string} scenario * @returns {Observable} Returns an RxJS observable that you can subscribe of in your code. * ``` - * content.Actions('ListItem') + * content.GetActions('ListItem') * .subscribe(response => { * console.log(response); * }, * error: error => console.error('something wrong occurred: ' + error.responseJSON.error.message.value)); * ``` */ - public Actions(scenario?: string): Observable { + public Actions(scenario?: string): Observable { + // tslint:disable-next-line:no-console + console.warn(`Method 'content.Action() is deprecated' and will be removed. Please use content.GetActions() instead`); + return this.GetActions(scenario); + } + + public GetActions(scenario?: string): Observable { return this._odata.Get({ path: ODataHelper.joinPaths(this.GetFullPath(), 'Actions'), params: { diff --git a/test/ContentTests.ts b/test/ContentTests.ts index 0851eeb..17d443b 100644 --- a/test/ContentTests.ts +++ b/test/ContentTests.ts @@ -591,22 +591,22 @@ export const contentTests = describe('Content', () => { ] } }); - contentSaved.Actions().subscribe((actions) => { + contentSaved.GetActions().subscribe((actions) => { expect(actions[0].Name).to.be.eq('Action1'); done(); }, done); - expect(contentSaved.Actions()).to.be.instanceof(Observable); + expect(contentSaved.GetActions()).to.be.instanceof(Observable); }); }); describe('#Actions()', () => { it('should return an Observable object', () => { - expect(contentSaved.Actions()).to.be.instanceof(Observable); + expect(contentSaved.GetActions()).to.be.instanceof(Observable); }); }); describe('#Actions()', () => { it('should return an Observable object', () => { - expect(contentSaved.Actions('ListItem')).to.be.instanceof(Observable); + expect(contentSaved.GetActions('ListItem')).to.be.instanceof(Observable); }); }); describe('#GetAllowedChildTypes()', () => { From e4a67632e578dfbb5428c3939d9d4c95809b92e7 Mon Sep 17 00:00:00 2001 From: Aniko Litvanyi Date: Tue, 5 Dec 2017 11:10:40 +0100 Subject: [PATCH 4/5] Fix minor typo in tryGetAsSaved's errormessage (#83) * chore(package): update @types/chai to version 4.0.5 (#78) * chore(package): update tslint-consistent-codestyle to version 1.10.2 (#79) * chore(package): update @types/chai to version 4.0.7 (#82) * Fix minor typo in tryGetAsSaved's errormessage --- package.json | 2 +- src/Content/ContentInternal.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 11a28f7..eaa2a39 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ }, "devDependencies": { "@types/app-root-path": "1.2.4", - "@types/chai": "4.0.5", + "@types/chai": "4.0.7", "@types/mocha": "2.2.44", "@types/node": "^8.0.0", "chai": "4.1.2", diff --git a/src/Content/ContentInternal.ts b/src/Content/ContentInternal.ts index 8ff2ead..3fa6eb1 100644 --- a/src/Content/ContentInternal.ts +++ b/src/Content/ContentInternal.ts @@ -187,7 +187,7 @@ if (isSavedContent(this)) { return this as SavedContent; } - throw new Error('Contnet is not saved.'); + throw new Error('Content is not saved.'); } /** From 60939e88a1a56095503e91bc0b909c97b97e70e2 Mon Sep 17 00:00:00 2001 From: gallayl Date: Tue, 5 Dec 2017 11:14:09 +0100 Subject: [PATCH 5/5] [KFI]chore(package): bumped version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index eaa2a39..8295229 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sn-client-js", - "version": "3.0.0", + "version": "3.0.1", "description": "A JavaScript client for Sense/Net ECM that makes it easy to use the REST API of the Content Repository.", "main": "dist/src/SN.js", "files": [