module Sfx { export class ImageStore extends DataModelBase < IRawImageStoreContent > { public static reservedFileName : string = "_.dir" ; public isAvailable : boolean = true ; public isNative : boolean = true ; public connectionString : string ; public root : ImageStoreFolder = new ImageStoreFolder ( ) ; public cachedCurrentDirectoryFolderSizes : { [ path ] : { size : number ; loading : boolean ; date ? : Date ; } ; } = { } ; public currentFolder : ImageStoreFolder ; public pathBreadcrumbItems : IStorePathBreadcrumbItem [ ] = [ ] ; private isLoadingFolderContent : boolean = false ; private initialized = false ; public static slashDirection ( path ) { return path . indexOf ( "\\" ) > - 1 ; } public static chopPath ( path ) { if ( ImageStore . slashDirection ( path ) ) { return path . split ( "\\" ) ; } return path . split ( "/" ) ; } constructor ( public data ) { super ( data ) ; this . root . path = "" ; this . root . displayName = "Image Store" ; this . currentFolder = this . root ; this . pathBreadcrumbItems = [ < IStorePathBreadcrumbItem > { path : this . root . path , name : this . root . displayName } ] ; let manifest = new ClusterManifest ( data ) ; manifest . refresh ( ) . then ( ( ) => { this . connectionString = manifest . imageStoreConnectionString ; this . isNative = this . connectionString . toLowerCase ( ) === "fabric:imagestore" ; if ( this . isNative ) { this . expandFolder ( this . currentFolder . path ) . then ( ( ) => { this . isAvailable = true ; } ) . catch ( err => { this . isAvailable = false ; } ) . finally ( ( ) => { this . initialized = true ; } ) ; } } ) ; } protected retrieveNewData ( messageHandler ? ) { if ( ! this . isNative || this . isLoadingFolderContent || ! this . initialized ) { return this . data . $q . resolve ( null ) ; } return this . expandFolder ( this . currentFolder . path ) ; } protected updateInternal ( ) { return this . data . $q . when ( true ) ; } protected expandFolder ( path , clearCache = false ) { if ( this . isLoadingFolderContent ) { return ; } this . isLoadingFolderContent = true ; return this . loadFolderContent ( path ) . then ( ( raw ) => { this . setCurrentFolder ( path , raw , clearCache ) ; let index = _ . findIndex ( this . pathBreadcrumbItems , item => item . path === this . currentFolder . path ) ; if ( index > - 1 ) { this . pathBreadcrumbItems = this . pathBreadcrumbItems . slice ( 0 , index + 1 ) ; } else { this . pathBreadcrumbItems . push ( < IStorePathBreadcrumbItem > { path : this . currentFolder . path , name : this . currentFolder . displayName } ) ; } this . isLoadingFolderContent = false ; return raw ; } ) . catch ( err => { this . isLoadingFolderContent = false ; if ( err . status === 400 ) { return err ; } else if ( err . status === 404 ) { this . data . message . showMessage ( `Directory ${ path } does not appear to exist anymore. Navigating back to the base of the image store directory.` , MessageSeverity . Warn ) ; return this . expandFolder ( this . root . path ) ; } } ) ; } public deleteContent ( path ) { if ( ! path ) { return this . data . $q . resolve ( ) ; } let item = _ . find ( this . currentFolder . childrenFolders , folder => folder . path === path ) ; if ( ! item ) { item = _ . find ( this . currentFolder . childrenFiles , file => file . path === path ) ; } if ( ! item || item . isReserved ) { return this . data . $q . resolve ( ) ; } return Utils . getHttpResponseData ( this . data . restClient . deleteImageStoreContent ( path ) ) . then ( ( ) => this . refresh ( ) ) ; } public getCachedFolderSize ( path ) { let cachedData = this . cachedCurrentDirectoryFolderSizes [ path ] ; if ( ! cachedData ) { cachedData = { size : - 1 , loading : false } ; this . cachedCurrentDirectoryFolderSizes [ path ] = cachedData ; } return cachedData ; } public getFolderSize ( path ) { return Utils . getHttpResponseData ( this . data . restClient . getImageStoreFolderSize ( path ) ) . then ( raw => { return raw ; } ) ; } private setCurrentFolder ( path , content , clearFolderSizeCache ) { if ( clearFolderSizeCache ) { this . cachedCurrentDirectoryFolderSizes = { } ; } let folder = new ImageStoreFolder ( ) ; folder . path = path ; let pathSegements = ImageStore . chopPath ( path ) ; folder . displayName = _ . last ( pathSegements ) ; folder . childrenFolders = _ . map ( content . StoreFolders , f => { let childFolder = new ImageStoreFolder ( f ) ; if ( childFolder . path in this . cachedCurrentDirectoryFolderSizes ) { childFolder . size = this . cachedCurrentDirectoryFolderSizes [ childFolder . path ] . size ; } return childFolder ; } ) ; folder . childrenFiles = _ . map ( content . StoreFiles , f => new ImageStoreFile ( f ) ) ; folder . allChildren = [ ] . concat ( folder . childrenFiles ) . concat ( folder . childrenFolders ) ; folder . fileCount = folder . childrenFiles . length ; this . currentFolder = folder ; } private loadFolderContent ( path , refresh = false ) { return this . data . $q ( ( resolve , reject ) => { Utils . getHttpResponseData ( this . data . restClient . getImageStoreContent ( path ) ) . then ( raw => { if ( refresh ) { this . setCurrentFolder ( path , raw , false ) ; } resolve ( raw ) ; } ) . catch ( err => { if ( err . status === 404 && path === this . root . path ) { resolve ( { StoreFiles : [ ] , StoreFolders : [ ] } ) ; } else { reject ( err ) ; } } ) ; } ) ; } } export class ImageStoreItem { public isFolder : number ; public path : string ; public displayName : string ; public isReserved : boolean ; public displayedSize : string ; public size : number ; public uniqueId : string ; constructor ( path ) { this . uniqueId = path ; this . path = path ; let pathSegements = ImageStore . chopPath ( path ) ; this . displayName = _ . last ( pathSegements ) ; this . isReserved = pathSegements [ 0 ] === "Store" || pathSegements [ 0 ] === "WindowsFabricStore" || this . displayName === ImageStore . reservedFileName ; } } export class ImageStoreFolder extends ImageStoreItem { public isFolder : number = - 1 ; public size : number = - 1 ; public fileCount : number ; public isExpanded : boolean = false ; public childrenFolders : ImageStoreFolder [ ] ; public childrenFiles : ImageStoreFile [ ] ; public allChildren : ImageStoreItem [ ] ; constructor ( raw ? ) { super ( raw ? raw . StoreRelativePath : "" ) ; if ( ! raw ) { return ; } this . path = raw . StoreRelativePath ; this . fileCount = + raw . FileCount ; } } export class ImageStoreFile extends ImageStoreItem { public isFolder : number = 1 ; public version : string ; public modifiedDate : string ; public size : number = 0 ; constructor ( raw ? ) { super ( raw ? raw . StoreRelativePath : "" ) ; if ( ! raw ) { return ; } this . path = raw . StoreRelativePath ; this . size = Number ( raw . FileSize ) ; this . displayedSize = Utils . getFriendlyFileSize ( this . size ) ; this . version = raw . FileVersion ? raw . FileVersion . VersionNumber : "" ; this . modifiedDate = raw . ModifiedDate ; } } export interface IStorePathBreadcrumbItem { path : string ; name : string ; } }