Vulcan: Transforms


#1

Vulcan development is flying!!!

Ever since the above post, we’ve had 2 significant rebuilds and loads of features assed to the Knowledge and Research Module alone.

With that in mind, and before I get opportunity to formally construct some proper documentation, I’ll add new documentation here… in no particular order (other than relevance to me at the time of writing)

Object Transforms

“Transforms” (for want of a better word, is when one object is used to generate new Objects of a certain type, based on some script, logic or criteria.

For example, I might add a Person Object to my chart with a Twitter account. A Transform I could run is to fetch this Person’s Twitter followers and generate new Person objects with the array of results.

Or, as in this example. I start with a Company object.

I add the Duedil Shareholders AddOn to fetch the companies registered shareholders.

For now, I’ve included a button, with an action to run the Transform.

So how did I create this Transform?

A Transform is simply a function which accesses the store create action to instantiate new Objects of the given type.

We provide an interface to this inside your components.

As you may know, Components are Vue.js components. For completeness, here’s the full component example, starting with the Template.

<template>
  <div>
    <v-layout row>
      <v-flex xs12>
        <v-card>
          <v-btn
           :loading="loading"
           :disabled="loading"
           color="secondary"
           @click="loader = 'loading'"
           >
           Start Transform
         </v-btn>
        <v-list three-line>
          <template v-for="(shareholder, index) in shareholders">
                   <v-list-tile :key="index" avatar @click="">
                   <v-list-tile-avatar>
                     <v-icon>verified_user</v-icon>
                   </v-list-tile-avatar>

                  <v-list-tile-content>
                    <v-list-tile-title v-html="shareholder.sourceName"></v-list-tile-title>
                      <v-list-tile-sub-title>
                        <v-chip small light color="pink" text-color="white">
                          <v-avatar><v-icon color="white">account_balance_wallet</v-icon></v-avatar>
                          {{formatShares(shareholder.totalShareholding)}} Shares
                        </v-chip>
                        <v-chip light small color="teal" text-color="white">
                          <v-avatar><v-icon color="white">pie_chart</v-icon></v-avatar>
                          {{formatSharesPerc(shareholder.totalShareholdingPercentage)}} %
                        </v-chip>
                     </v-list-tile-sub-title>
                   </v-list-tile-content>
              
                 </v-list-tile>
                <v-divider></v-divider>
              </template>
            </v-list>
          </v-card>
        </v-flex>
      </v-layout>
    </div>
</template>

And our style for the animated button:

<style scoped>
    custom-loader {
    animation: loader 1s infinite;
    display: flex;
  }
  @-moz-keyframes loader {
    from {
      transform: rotate(0);
    }
    to {
      transform: rotate(360deg);
    }
  }
  @-webkit-keyframes loader {
    from {
      transform: rotate(0);
    }
    to {
      transform: rotate(360deg);
    }
  }
  @-o-keyframes loader {
    from {
      transform: rotate(0);
    }
    to {
      transform: rotate(360deg);
    }
  }
  @keyframes loader {
    from {
      transform: rotate(0);
    }
    to {
      transform: rotate(360deg);
    }
  }
</style>

OK, now onto the scripts.

<script>
    module.exports = {
        name: 'TestTransform',
        props: {
            countryCode: {
                type: String,
                default: "gb"
            },
            companyId: {
                type: String,
                default: "06999618"
            }
        },
        mounted: function() {
          let options = {
              headers: {
                    'Accept': 'application/json',
                    'X-AUTH-TOKEN': '<AUTH_TOKEN>'
                  }
          }
          
          let params = {
                  countryCode: this.countryCode,
                  companyId: this.companyId
              }
          
          this.$http.get('https://duedil.io/v4/company/' + params.countryCode + '/' + params.companyId + '/shareholders.json', options)
            .then(function(result){
                console.log(result);
                this.shareholders = result.body.shareholders
            }, function(error){
                console.log('Error: ' + error.message)
            })
            
        },
        data: function () {
          return {
              shareholders: [{'sourceName': 'Steve', 'totalShareholding': 9888926, 'totalSharesPercentage': 27.685}],
              loader: null,
              loading: false,
          }
        },
        methods: {
            formatShares(value){
                return value.toLocaleString('en');
            },
            formatSharesPerc(value){
                return parseFloat(value).toFixed(2);
            },
            guid() {
             const guid = function() {
              function s4() {
               return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
              }
              return (s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4());
             };  
            },
            // INSERT Transform Method
            }
        },
        watch: {
         loader () {
          const l = this.loader
          this[l] = !this[l]
          
          // CALL TRANSFORM METHOD
          this.transformGeneratePersonObjects()

          setTimeout(() => (this[l] = false), 3000)

          this.loader = null
         }
        },
        computed: {}
    }
</script>

Ok, now we have the full component in place, we just need to add our transformGeneratePersonObjects() method.

transformGeneratePersonObjects(){
    // we could do something much smarter with object layout, but let's keep it simple
    const x = 1000 + (Math.floor(Math.random()*100)+100);
    const y = 1000 + (Math.floor(Math.random()*100)+100);
    
    // iterate over our Shareholders array
    for (var i = 0, l = this.shareholders.length; i < l; i++) {
        var shareholder = this.shareholders[i];
        const text = shareholder.sourceName + ' holds ' + shareholder.totalShareholding + ' shares, equating to ' + shareholder.totalShareholdingPercentage + '% of the available shares.'
        // this is the magic
         const objectPromise = this.$store.dispatch('object/create', {
            type: "AnalysisTools_PersonObject",
            position: {x, y},
            info: {
               title: shareholder.sourceName,
                settings: {
                    title: shareholder.sourceName,
                    notesLines: [{id: this.guid(), content: text, type: "Text"}]
                 }
              }
              }).then(function(createdObject){
                  console.log('Created object: ' + createdObject.id);
              })
        }
}

Project Vulcan - Knowledge & Research Module