How to Build Media Applications With Vidispine Development Toolkit (pt2)

By Filip - September 13, 2018

In this part 2 of the Vidispine Development Toolkit tutorial you will learn how to start using the components, make API calls to the Vidispine API and finally import a file into the repository.

 

Introduction

In this blog post, we are going to set up and configure our project to implement the vdt-vue-components and use few of them to list all storages for our instance, list all importable files for the selected storage and import the selected files from that storage.

All the components that we are going to create should be located in [my-project]/src/components. Default welcome page that is visible when we have just set up the VDT is named VidispineVersion.vue and can be used as a learning reference.

All code can be found in the companion Github repo howto-build-vdt-applications. If you haven’t set up your system yet, head over to part 1 of the tutorial.

This blog post

  • Clone vdt-vue-components repository
  • Configure our project to use vdt-vue-components
  • List all Vidispine Instance Storages and files from each storage
  • List all files from the selected Storage
  • Add new vdt-vue-component to our custom component to list files
  • Import the selected file(s) to Vidispine Instance

Vdt-vue-components focused on

VdtList.

Clone vdt-vue-components repository.

Navigate to our VDT project root folder:

$ cd ~/VDT

Clone the vdt-vue-components repository, this will create a folder for you.

$ git clone git@github.com:vidispine/vdt-vue-components.git

Quick Reference:

https://github.com/vidispine/vdt-vue-components

Configure our project to use vdt-vue-components.

Navigate to the previously  cloned repository folder:

$ cd ~/VDT/vdt-vue-components/

Create components link. You should see output in terminal that says -> success Registered “@vidispine/vdt-vue-components”. Run the following command to create a link:

$ yarn link

Navigate to our project which is “my-project”

$ cd ~/VDT/my-project

Link the components to our project with the registration ID we got in the previous step:

$ yarn link @vidispine/vdt-vue-components

Optional “cherry on top”:

To get immediate page refresh when saving document, ESLint checking and other goodies.

In new terminal, change to vdt-vue-components directory, Run the following command to install all the dependencies:

$ cd ~/VDT/vdt-vue-components/

$ yarn install

Run one of the following “watch” commands to build on save

– Any modern app running ES6 or later:

$ yarn watch

– Non ES6 projects

$ yarn watch-umd

Additionally you can run tests to double check if everything is running as is should

$ yarn test

Building the application

Create a new file in ‘src/components’ and name it Import.vue. Leave it for now and instead head into the ‘router’ folder and open the index.js file within. Import the newly created Import.vue and create a new object within ‘routes’, this will enable you to navigate to ‘http://localhost:4000/import’. Then, head into the ‘assets’ folder and then ‘scss’ to find ‘base.scss’. Open it and add a new import, enabling the stylesheet for the VDT components.

In index.js, add the following import:

import Import from '../components/Import.vue';

and the following route:

{
    path: '/import',
    name: 'import',
    component: Import,
}

In ‘base.scss‘:

@import '~@vidispine/vdt-vue-components/es/index.css';

Head back into the newly created ‘Import.vue’. The API calls used to import files from select storages are handled in functions imported to the application, in this case, three different functions and one dependency are imported and used. Initially, the storages have to be retrieved and made available to use in the application, and from these files has to be retrieved in turn. All imports are placed at the very top inside the script tags, let’s go ahead and import these first to functions to enable them in the application.

<script> 
    import storageApi from '../api/storage.api';
    /* 'http://apidoc.vidispine.com/latest/ref/storage/storage.html#retrieve-list-of-storages' */ 
    import fileApi from '../api/file.api'; 
    /* 'http://apidoc.vidispine.com/latest/ref/storage/file.html#start-an-import-job' */ 

   export default { 
      name: 'Import', 
   }; 
</script>

These imports can then be called upon inside the application itself. to simplify things, we can create three empty arrays inside a data function, to in turn store the response received from the API calls, for example – files, hits, and storages. Following that, the storage retrieval can be called upon and its response stores in the newly created ‘storages’ array. With a storage identified and selected, retrieving files from it is done in a similar manner, although the API call for retrieving files requires the ID of a storage. 

<script>
import storageApi from '../api/storage.api';
import fileApi from '../api/file.api';

export default {
  name:'Import',
  data() {
    return {
      storages: [],
      files: [],
      selectedStorage:'',
    };
  },

  watch: {
    selectedStorage(newStorage) {
      this.getFiles(newStorage);
    },
  },

  mounted() {
    storageApi.getStorages().then((response) => {
      this.storages=response;
    });
  },

  methods: {
    getFiles(storageId) {
      returnfileApi.getImportableFiles(storageId).then((response) => {
        this.files=response.files.files;
      });
    },
  },
};
</script>

The storages and its content are now available in the application. Let us create some HTML elements to handle the different function calls and actually display something for the user. the number of storages may vary, so browsing between the different storages might be a good idea. With a storage selected, the ‘getFiles’ function needs to be called with the ID of the storage, in this case, the ‘selectedStorage’ object is assigned the ID of the storage and passed on with the ‘getFiles’ function.

<template>
  <div class="import">
    <h1>Import</h1>
    <select
      v-model="selectedStorage">
      <option
        disabled
        value="">
        Select a storage
      </option>
      <option
        v-for="storage in storages"
        :key="storage.id"
        :value="storage.id">
        {{ storage.name }}
      </option>
    </select>
    <ul>
      <li
        v-for="file in files"
        :key="file.id">
        {{ file.id }}
      </li>
    </ul>
  </div>
</template>

In this example, the function is bound to a ‘watch’ function that triggers each time the watched object (‘selectedStorage’) changes. Add the code below to your <script> section.

watch: {
  selectedStorage(newStorage) {
    this.getFiles(newStorage);
  },
},

With all of the above implemented, a list with importable files should be displayed.

VDT - Bucket dropdown with importable files

Adding the VdtList component

Although already functioning properly, let’s use the list component included in the vdt-vue-components repository instead. This specific component requires three properties to function, an array of assets, an array of columns, and an array of selected files, along with some optional properties should you wish to utilize them as well. Firstly, we create the array of columns, the ‘key’ property is the path metadata within the file.

In ‘src/assets/scss/base.scss‘,  add the import below at the top.

@import '~@vidispine/vdt-vue-components/dist/vdt-vue-components.css';

In Import.vue add the following code in the <template>, <script> and <style> sections:

<template>
...code snippet...
<VdtList
  :assets="files"
  :columns="columns"
  :checkbox="true"
  :track-by="'id'"
  :selected-assets="selectedAssets"/>
...code snippet...
</template>
<script>
...
export default {
name: 'Import',
  components: {
    VdtList,
  },

  data() {
    return {
      storages: [],
      files: [],
      selectedStorage: '',
      selectedAssets: [],
      columns: [
        {
          label: 'Path',
          key: 'path',
          type: 'String',
          size: 'large',
        },
        {
          label: 'Date',
          key: 'timestamp',
          type: 'Date',
          size: 'medium',
        },
        {
          label: 'Size',
          key: 'size',
          type: 'Size',
          size: 'small',
        },
      ],
    };
  },
};

<style lang="scss">
.import {
 position: relative;
 width: 100%;
 height: 100%;
 font-size: 2em;
}
.vdt-list-row__selected {
 background-color: lightblue;
}
</style>

The list should now look a bit more structured with column headers and checkboxes, making each file selectable. The initially empty ‘selectedAssets’ array should also update each time a file is selected, and functions as the basis in the import function.

VdtList with styling

Adding import functionality

Since the API call for the import is made from within the application it needs some functionality to handle that.  ‘axios’ is the solution for that, which is also used in the imported functions. The ‘JobPollService’ is optional, but helps keep track of the import process and updates its status continuously. The ‘destroyed()’ function resets all intervals upon import completion.

So, let’s add the last pieces of code in Import.vue that are required to import a file from a storage. We need a button for import in the <template> section.

<button
 :disabled="selectedAssets.length < 1"
 @click="importFiles()">
 Import
</button>

…and then add a ‘destroyed()’ function, and a new method ‘importFiles()’ in the <script> part:

importFiles() {
    this.selectedAssets.forEach((file) => {
      const data = {/* insert custom data here, tags etc. */};
      const fileExtention = file.path.substr(file.path.lastIndexOf('.') + 1);
      if (['png', 'jpg', 'JPG', 'jpeg', 'gif', 'webp', 'tiff', 'bmp'].indexOf(fileExtention) > -1) {
        data.tag = '__jpeg';
      } else if (['mp4', 'mov', 'avi', 'mkv', 'flv', 'webm', 'wmv', 'mpeg', 'mpg', 'mpv', 'm4v', 'mxf'].indexOf(fileExtention) > -1) {
        data.tag = '__mp4';
      }

      axios.post(`/api/storage/${this.selectedStorage}/file/${file.id}/import`, data)
        .then((response) => {
          const job = new JobPollService({
            jobId: response.data.jobId,
            milliseconds: 2000,
            asset: file,
          });
          job.startInterval();
        });
    });
  },

Your code should now look like Import.vue in the howto-build-vdt-applications Github repository. You should now see an import-button after the file list, and if you select a file and import it will be imported into your Vidispine instance. Check for yourself that your file is imported by pointing your browser to:

https://[yourvidispineapiinstance].myvidispine.com/API/item?content=metadata&field=originalFilename&terse=yes

That concludes part 2. In the next part of the tutorial you will learn how to create a grid with item preview, and use the player.