Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This is the third part of the Vidispine VidiCore Development Toolkit tutorial, where you’ll learn yo use a grid component to show repository items, as well as how to preview different types of items in the system. When finished you should be able to import and play/show videos and images.

Introduction

Welcome to the third part of the Vidispine VidiCore Development Toolkit tutorial. In this part, we’ll add a grid with repository items using the VdtGrid component, and show how you can preview items such as images, and video together with their metadata using VdtShape, VdtMetadata, VdtImagePreview, and VdtVideoPlayer components.

This blog

Table of Contents

Getting started

All the Vue components that we are going to create should be located in [my-project]/src/components. The default welcome page that is visible when we have just set up the Vidispine VidiCore Development Toolkit 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, and then part 2 to learn how to build the import component.

Wrapper, items, and preview

Start by creating a new Vue component file within the components folder, and call it Front.vue. Create two additional files, at the same level as the wrapper file, and name them Items.vue and Preview.vue. Import the import (from part 2 of the tutorial), items and preview Vue components to your wrapper component, then declare them as Vue components.

...

Code Block
<template>
  <div class="media-supply-chain-wrapper">
    <Import/>
    <Items/>
    <Preview/>
  </div>
</template>

<script>
import Import from './Import.vue';
import Items from './Items.vue';
import Preview from './Preview.vue';

export default {
  name: 'MediaSupplyChain',
  components: {
    Import,
    Items,
    Preview,
  },
};
</script>

<style lang="scss" scoped>
.media-supply-chain-wrapper {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  grid-column-gap: 1em; height: 100vh;
  font-size: 1rem;
}
</style>

Adding VDTgrid

Head into your Items.vue file and start by importing and declaring the grid component and the itemApi function. Inside a mounted() function, call the itemApi function to retrieve the items previously imported to the application.

...

Code Block
<VdtGrid
  :assets="assets"
  @assetClick="$emit('selected', $event)"/>

Connecting items and preview

The function is now forwarded to the parent, in this case, the wrapper created earlier. Set up the same listener in the wrapper document and now bind it to a function, in the example below it is named select. The item ID is extracted from the object and passed to the itemId data object, which is then passed on to the preview Vue component.

...

Code Block
<template>
  <div class="media-supply-chain-wrapper">
    <Import/>
    <Items @selected="select($event)"/>
    <Preview :item-id="itemId"/>
  </div>
</template>

<script>
export default {
  name: 'MediaSupplyChain',
  components: {
    Import,
    Items,
    Preview,
  },
  data() {
    return {
      itemId: '',
    };
  },
  methods: {
    select(asset) {
      this.itemId = asset.metadata.id;
    },
  },
};
</script>

Building the preview document

Head over to the Preview.vue file and import the necessary components and set up the prop sent by the parent wrapper component earlier.

...

Code Block
<script>
// eslint-disable-next-line import/no-extraneous-dependencies  
import { VdtShape, VdtMetadata, VdtImagePreview, VdtVideoPlayer } from '@vidispine/vdt-vue-components/es';

export default {
  name: 'Preview',
  components: {
    VdtShape,
    VdtMetadata,
    VdtImagePreview,
    VdtVideoPlayer,
  },
  props: {
    itemId: {
      type: String,
      required: true,
    },
  },
};
</script>

Retrieve shapes and metadata

To retrieve the shapes and metadata specific to singular items, another API call has to be made. Import the itemApi function used earlier. For this specific example, the preview is expected to update as the user selects the different items in the grid. Create a new object called item that is empty by default, and assign the response from the API call to it.

...

Code Block
import itemApi from '../api/item.api';
data() {
  return {
    item: {},
  };
},
watch: {
  itemId(newVal, oldVal) {
    if (oldVal === null || newVal !== oldVal) {
      itemApi.getItem(this.itemId).then((response) => {
        this.item = response;
      });
    }
  },
},

Adding image and metadata preview

An item can have multiple shapes, and displaying all of them at once would affect the system in an unnecessary way. The VdtImagePreview component requires a shape as an object to work, rendering the array of shapes received from the API call incompatible. Create a select input similar to the one in the import component, and list the available shapes there, and then send the selected shape the way of the VdtImagePreview component.

...

Code Block
<template>
  <div class="item-preview">
    <div v-if="item">
      <div class="preview-item">
        <select
          v-model="selectedShape">
            <option
              disabled
              value="">
              Select a shape
            </option>
            <option
              v-for="shape in item.shapes"
              :key="shape.id"
              :value="shape">
              {{ shape.tag }}
            </option>
          </select>
          <div v-if="selectedShape">
          <VdtImagePreview
            :shape="selectedShape"/>
        </div>
      </div>
    </div>
  </div>
</template>

data() {
  return {
    item: {},
    selectedShape: '',
  };
},

watch: {
  itemId(newVal, oldVal) {
    if (oldVal === null || newVal !== oldVal) {
      itemApi.getItem(this.itemId).then((response) => {
        this.item = response;
        [this.selectedShape] = [response.shapes[0]];
      });
    }
  },
},

Adding metadata preview

The VdtMetadata component requires an array of rows and the asset, as an object. The key within the row objects is the path to the metadata values and can vary depending on the database and metadata structuring. For now, let’s add four labels with corresponding paths.

...

Code Block
<div v-if="selectedShape">
  <VdtImagePreview
    :shape="selectedShape"/>
  <VdtMetadata
    :asset="item"
    :rows="rows"/>
</div>

data() {
  return {
    item: {},
    selectedShape: '',
    rows: [
      {
        label: 'Title',
        key: 'metadata.filename',
        type: 'String',
      },
      {
        label: 'Type',
        key: 'metadata.mediaType',
        type: 'String',
      },
      {
        label: 'Format',
        key: 'metadata.originalFormat',
        type: 'String',
      },
      {
        label: 'Created',
        key: 'metadata.created',
        type: 'Date',
      },
    ],
  };
},

Adding a video player

The component can now display images, as well as display the metadata related to the item being previewed. Let’s add the VdtVideoPlayer to enable the previewing of items with video formats as well, along with a computed property that returns the mediaType of the item. Using this property, it is now possible to display either the VdtImagePreview component or the VdtVideoPlayer component depending on the media type of the item.

...