import { BaseVirtualField , BaseVirtualFieldParams } from './base' ; import { Backend } from '../base-backend' ; import { Record , RecordRawData , RecordStateData , RelFieldChangedEvent } from '../datatypes/record' ; import { SaveQuery , ChildQueryDescriber } from '../query/query' ; import { Subscription } from 'rxjs' ; export interface ForeignKeyVirtualFieldParams extends BaseVirtualFieldParams { model : string ; keys : { [ localFieldName ] : string ; } ; } export class ForeignKeyVirtualField extends BaseVirtualField { internalName = 'ForeignKeyVirtualField' ; model : string ; keys : { [ localFieldName ] : string ; } ; constructor ( backend , params ) { super ( backend , params ) ; this . model = params . model ; this . keys = params . keys ; } prepareValue ( record , oldValue , newValue ) { if ( newValue && newValue instanceof Record ) { var subscriptions = [ ] ; subscriptions . push ( newValue . __director__ . changed . subscribe ( ev => { record . __director__ . isChildrenChanged = true ; record . __director__ . changed . next ( new RelFieldChangedEvent ( this . name , newValue , ev ) ) ; } ) ) ; record . __director__ . fieldData . set ( this . name , subscriptions ) ; } } destroyValue ( record ) { if ( record . __director__ . fieldData . has ( this . name ) ) { var subscriptions = record . __director__ . fieldData . get ( this . name ) as Subscription [ ] ; subscriptions . forEach ( s => s . unsubscribe ( ) ) ; } } constructRelRecordData ( source ) { var recordData = { [ this . backend . modelNameField ] : this . model } ; for ( let key in this . keys ) { recordData [ this . keys [ key ] ] = source [ key ] ; } return recordData ; } dataChanged ( fields = null , record , emitChange ) { var fieldsHave = false ; if ( fields instanceof Array ) { for ( let k in this . keys ) { if ( fields . indexOf ( k ) !== - 1 ) { fieldsHave = true ; break ; } } } if ( fields == null || fieldsHave ) { var virtualFieldMustBeEmpty = false ; var valueToSet ; for ( let key in this . keys ) { var f = record . __director__ . model . getDbField ( key ) ; if ( record [ key ] == f . getEmptyValue ( ) ) { virtualFieldMustBeEmpty = true ; break ; } } if ( virtualFieldMustBeEmpty ) { if ( record [ this . name ] !== null ) { valueToSet = null ; } } else { var recordData = this . constructRelRecordData ( record ) ; var isVirtualNeedToBeChanged = false ; for ( let key in this . keys ) { if ( ! ( record [ this . name ] instanceof Record ) || ( record [ this . name ] as Record ) [ this . keys [ key ] ] !== record [ key ] ) { isVirtualNeedToBeChanged = true ; break ; } } if ( isVirtualNeedToBeChanged ) { var model = this . backend . getRecordModel ( this . model ) ; valueToSet = model . constructRecord ( false , recordData ) ; } } if ( valueToSet !== undefined ) { var data = { } ; data [ this . name ] = valueToSet ; record . __director__ . setValues ( data , emitChange ) ; } } else if ( fields . indexOf ( this . name ) !== - 1 ) { if ( ! record [ this . name ] ) { var data = { } ; for ( let key in this . keys ) { var f = record . __director__ . model . getDbField ( key ) ; data [ key ] = f . getEmptyValue ( ) ; } record . __director__ . setValues ( data , emitChange ) ; } else if ( record [ this . name ] instanceof Record ) { record . __director__ . setValues ( this . getRealValues ( record [ this . name ] , record ) , emitChange ) ; } } } getRealValues ( virtualValue , hostRecord ) { var data = { } ; for ( let key in this . keys ) { if ( this . keys [ key ] in virtualValue && virtualValue [ this . keys [ key ] ] !== hostRecord [ key ] ) { data [ key ] = virtualValue [ this . keys [ key ] ] ; } } return data ; } fromInternalToRAW ( value ) { if ( value instanceof Record ) { return value . __director__ . extractRAWData ( ) ; } else { return null ; } ; } fromRAWtoInternal ( rawData ) { var model ; if ( this . backend . modelNameField in rawData ) model = rawData [ this . backend . modelNameField ] ; else model = this . model ; return this . backend . getRecordModel ( model ) . constructRecord ( false , rawData ) ; } getSaveQueries ( value ) { if ( ! value || ! value . __director__ . isFull ) return null ; var result = [ ] ; return [ { handle : '' , query : value . __director__ . getSaveQuery ( ) } ] ; } }