import { Component } from 'vue-property-decorator' ; import _ from 'lodash' ; import ns from '@/store/namespaces' ; import template from './data-reservoir.html' ; import { injectNodeTemplate } from '../node' ; import { SubsetOutputPort } from '../port' ; import { GetDatasetOptions } from '@/store/dataset/types' ; import { SubsetNode } from '../subset-node' ; import * as history from './history' ; interface DataReservoirSave { items : number [ ] ; } @ Component ( { template : injectNodeTemplate ( template ) } ) export default class DataReservoir extends SubsetNode { public isInputOutputDisconnected = true ; protected NODE_TYPE = 'data-reservoir' ; protected DEFAULT_HEIGHT = 40 ; protected RESIZABLE = true ; @ ns . user . State ( 'username' ) private username ! : string ; @ ns . dataset . Action ( 'getDataset' ) private dispatchGetDataset ! : ( options : GetDatasetOptions ) => Promise < string > ; private items : number [ ] = [ ] ; private heldItems : number [ ] = [ ] ; private isOutputChanged = false ; private toPropagate = false ; public setItems ( items ) { this . setOutputSubset ( items ) ; this . items = items ; this . propagate ( ) ; } protected created ( ) { this . serializationChain . push ( ( ) : DataReservoirSave => { return { items : this . items } ; } ) ; this . deserializationChain . push ( ( ) => { if ( this . items . length ) { this . toPropagate = true ; } } ) ; } protected onDatasetChange ( ) { } protected update ( ) { if ( ! this . checkDataset ( ) ) { return ; } this . checkOutputChange ( ) ; if ( this . toPropagate ) { this . toPropagate = false ; this . setItems ( this . items ) ; } } protected createOutputPorts ( ) { this . outputPorts = [ new SubsetOutputPort ( { data : { id : 'out' , node : this , isMultiple : true } , store : this . $store } ) , ] ; } /**
     * Computes and returns the output subset.
     */ private computeOutput ( ) { const inputPort = this . inputPortMap . in ; if ( ! inputPort . hasPackage ( ) ) { return [ ] ; } const pkg = inputPort . getSubsetPackage ( ) ; const dataset = pkg . getDataset ( ) ; if ( ! dataset ) { return [ ] ; } return pkg . getItemIndices ( ) ; } /**
     * Computes the output subset and saves it on the output port.
     * However, it does not release the subset.
     */ private updateOutputItems ( items ) { const inputPort = this . inputPortMap . in ; if ( ! items . length ) { if ( ! inputPort . hasPackage ( ) || ! inputPort . getSubsetPackage ( ) . hasDataset ( ) ) { this . updateNoDatasetOutput ( ) ; } return ; } const pkg = inputPort . getSubsetPackage ( ) ; this . updateOutput ( pkg . clone ( ) ) ; } /**
     * Sets the output subset to the given subset.
     * This is used by undo.
     */ private setOutputSubset ( items ) { const inputPort = this . inputPortMap . in ; if ( ! inputPort . hasPackage ( ) || ! inputPort . getSubsetPackage ( ) . hasDataset ( ) ) { this . updateNoDatasetOutput ( ) ; return ; } const pkg = inputPort . getSubsetPackage ( ) ; this . updateOutput ( pkg . subset ( items ) ) ; } private releaseOutput ( ) { const prevItems = this . items . concat ( ) ; this . items = this . computeOutput ( ) ; this . updateOutputItems ( this . items ) ; this . propagate ( ) ; this . isOutputChanged = false ; this . commitHistory ( history . releaseOutputEvent ( this , this . items , prevItems ) ) ; } private checkOutputChange ( ) { this . heldItems = this . computeOutput ( ) ; this . isOutputChanged = ! _ . isEqual ( this . heldItems , this . items ) ; } private clearOutput ( ) { this . updateNoDatasetOutput ( ) ; this . propagate ( ) ; this . commitHistory ( history . clearOutputEvent ( this , this . items ) ) ; } }