Skip to main content
Skip table of contents

How to build media applications with VidiCore Development Toolkit (PT2)

In this part 2 of the VidiCore Development Toolkit tutorial, you will learn how to start using the components, make API calls to the VidiCore 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 post

VDT-VUE-Components focused on

VdtList.

Install VDT UI Components

What you need to do is head over to your application folder and, depending on if you are using yarn or npm, run one of the commands below to install.

Note: The vdt-vue-components NPM package is private and you have to login before you can install it. 

CODE
npm login

# if you are using yarn
yarn add @vidispine/vdt-vue-components

#if you are using npm
npm install @vidispine/vdt-vue-components --save

If you also want to change the components and learn how they actually work, you will also need to make sure you get access to the GitHub repository, and then clone and link your application.

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 ‘https://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:

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

and the following route:

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

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

CODE
@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.

CODE
<script> 
    import storageApi from '../api/storage.api';
    /* 'https://apidoc.vidispine.com/latest/ref/storage/storage.html#retrieve-list-of-storages' */ 
    import fileApi from '../api/file.api'; 
    /* 'https://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. 

CODE
<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) {
      return fileApi.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.

CODE
<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.

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

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

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 an array of columns, the ‘key’ property is the path metadata within the file.

CODE
$body

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

CODE
<template>
  <div class="import">
<!-- add the following snippet here -->
    <VdtList
      :assets="files"
      :columns="columns"
      :checkbox="true"
      :track-by="'id'"
      :selected-assets="selectedAssets"/>
<!-- end of snippet -->
  </div>
</template>
<script>
// extend <script> with the following code

// eslint-disable-next-line import/no-extraneous-dependencies
import { VdtList } from '@vidispine/vdt-vue-components/es';
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',
        },
      ],
    };
  },
  
  // rest of the code 

};
</script>

<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.

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.

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

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

CODE
import axios from 'axios';

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 VidiCore instance. Check for yourself that your file is imported by pointing your browser to:

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

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


Related pages

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.