1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | 1x 1x 1x 1x 1x 1x 13807x 2x 5x 5x 5x 1x 1x 2x 2x 1x 1x 5x 2x 1x 1x 1x 2x 2x 1x 1x 5x 1x 2x 2x 14x 3x 11x 1x 11x 1x 11x 327x 9310x 12x 9298x 14x 9310x 8900x 8900x 8900x 8900x 8900x 1x 2x 2x 9x 2x 7x 2x 7x 2x 7x 211x 3x 3x 5145x 7x 5138x 8x 5145x 4907x 4907x 4907x 4907x 4907x | /** * @module Content */ /** */ import { Observable } from 'rxjs/Observable'; 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'; export abstract class ReferenceAbstract<T extends IContent> { public readonly abstract FieldSetting: ReferenceFieldSetting; public readonly abstract Repository: BaseRepository; protected _isDirty: boolean = false; public get IsDirty(): boolean { return this._isDirty; } /** * Executes a search query to lookup possible values to the reference field * @param { string } term This term will be searched in the _Text field * @param { number } top The Top value for paging * @param { number } skip The Skip value for paging * @param { IOdataParams } odataParams The additional OData params (like select, expand, etc...) * @returns { FinializedQuery } The FinializedQuery instance that can be executed * * Example: * ```ts * reference.Search('Term').Exec().subscribe(hits=>{ * console.log(hits); * }); * ``` */ public Search(term: string, top: number = 10, skip: number = 0, odataParams: IODataParams<T> = {}): FinializedQuery<T> { return new FinializedQuery((q) => { let query = q.Equals('_Text', `*${term}*`); if (this.FieldSetting.SelectionRoots && this.FieldSetting.SelectionRoots.length) { query = query.And.Query((innerTree) => { this.FieldSetting.SelectionRoots && this.FieldSetting.SelectionRoots.forEach((root, index, thisArray) => { (innerTree as any) = innerTree.InTree(root); if (index < thisArray.length - 1) { innerTree = (innerTree as any).Or; } }); return innerTree; }); } if (this.FieldSetting.AllowedTypes && this.FieldSetting.AllowedTypes.length) { const foundTypes = this.FieldSetting.AllowedTypes.map((type) => (ContentTypes as any)[type] as {new(...args: any[]): T}).filter((a) => a !== undefined); Eif (foundTypes.length > 0) { query = query.And.Query((innerTypes) => { foundTypes.forEach((type, index, thisArray) => { (innerTypes as any) = innerTypes.Type(type); if (index < thisArray.length - 1) { innerTypes = (innerTypes as any).Or; } }); return innerTypes; }); } } return query.Top(top).Skip(skip); }, this.Repository, '/Root', odataParams); } } /** * Represents a Reference field on a Content object. Example: * ```ts * let myTask = repository.Load('/Root/MyTasks/Task1', {expand: ['Owner']}).subscribe(task => { * task.Owner.GetContent(owner => { * console.log('The Owner of the task is:', owner.DisplayName); * }) * }, error => console.error) * ``` * */ export class ContentReferenceField<T extends IContent> extends ReferenceAbstract<T> { private _contentReference: SavedContent<T>; private _referenceUrl: string; /** * Updates the reference value to another Content * @param {T} content The new Content value */ public SetContent(content: SavedContent<T>) { this._contentReference = content; this._isDirty = true; } /** * Gets the current reference value. * @param {ODataParams} odataOptions Additional options to select/expand/etc... * @returns {Observable<T>} An observable that will publish the referenced content */ public GetContent(odataOptions?: IODataParams<T>): Observable<SavedContent<T>> { if (!this._ownerContent.IsSaved || this._contentReference !== undefined) { return Observable.of(this._contentReference); } 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<T>(r.d); }).share(); request.subscribe((c) => { this._contentReference = c; }); return request; } /** * @returns The reference value (content Path) that can be used for change tracking and content updates. */ public GetValue(): string | undefined { return this._contentReference && this._contentReference.Path; } /** * Updates the reference URL in case of DeferredObject (not-expanded-fields) or populates the Content reference (for expanded fields) from an OData response's Field * @param {DeferredObject | T['options']} fieldData The DeferredObject or ContentOptions data that can be used */ public HandleLoaded(fieldData: DeferredObject | SavedContent<T>) { if (isDeferred(fieldData)) { this._referenceUrl = fieldData.__deferred.uri.replace(this.Repository.Config.ODataToken, ''); } else if (isIContent(fieldData)) { this._contentReference = this.Repository.HandleLoadedContent<T>(fieldData); } this._isDirty = false; } constructor(fieldData: DeferredObject | SavedContent<T>, public readonly FieldSetting: ReferenceFieldSetting, private readonly _ownerContent: SavedContent, public readonly Repository: BaseRepository) { super(); this.HandleLoaded(fieldData); } } /** * Represents a Reference list field on a Content object. Example: * ```ts * let myTask = repository.Load('/Root/MyTasks/Task1', {expand: ['Versions']}).subscribe(versions => { * task.Versions.GetContent(versions => { * console.log('The available versions are:', versions); * }) * }, error => console.error) * ``` * */ export class ContentListReferenceField<T extends IContent> extends ReferenceAbstract<T> { private _contentReferences: SavedContent<T>[]; private _referenceUrl: string; /** * Updates the reference list to another Content list * @param {T[]} content The new list of content */ public SetContent(content: SavedContent<T>[]) { this._contentReferences = content; this._isDirty = true; } /** * Gets the current referenced values. * @param {ODataParams} odataOptions Additional options to select/expand/etc... * @returns {Observable<T[]>} An observable that will publish the list of the referenced content */ public GetContent(odataOptions?: IODataParams<T>): Observable<SavedContent<T>[]> { if (!this._ownerContent.IsSaved || this._contentReferences) { return Observable.of(this._contentReferences); } // const request = this.Repository.GetODataApi().Fetch<T>({ 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<T>(c)) || []; }).share(); request.subscribe((c) => { this._contentReferences = c; }); return request; } /** * @returns The reference value (content Path list) that can be used for change tracking and content updates. */ public GetValue(): string[] | undefined { return this._contentReferences && this._contentReferences .filter((c) => c.Path && c.Path.length) .map((c) => c.Path as string); } /** * Updates the reference URL in case of DeferredObject (not-expanded-fields) or populates the Content list references (for expanded fields) from an OData response's field * @param {DeferredObject | T['options'][]} fieldData The DeferredObject or ContentOptions data that can be used */ public HandleLoaded(fieldData: DeferredObject | T[]) { if (isDeferred(fieldData)) { this._referenceUrl = fieldData.__deferred.uri.replace(this.Repository.Config.ODataToken, ''); } else if (isIContentList(fieldData)) { this._contentReferences = fieldData.map((f) => this.Repository.HandleLoadedContent(f as SavedContent)); } this._isDirty = false; } constructor(fieldData: DeferredObject | T[], public readonly FieldSetting: ReferenceFieldSetting, private readonly _ownerContent: SavedContent, public readonly Repository: BaseRepository) { super(); this.HandleLoaded(fieldData); } } |