<script>
import TestService from '@/services/TestService';
import _ from 'lodash';
export default {
name: 'videos',
data() {
return {
videos: [],
page: {
data: [],
ippOptions: {
4: 4,
6: 6,
8: 8,
10: 10,
12: 12,
14: 14,
18: 18,
},
filters: {
// Check to see if an Items Per Page setting was set in the URL
// If not, default to 12 items per page
ipp: (this.$route.query.hasOwnProperty('ipp'))?this.$route.query.ipp:12,
page: (this.$route.query.hasOwnProperty('page'))?this.$route.query.page:1,
product: (this.$route.query.hasOwnProperty('product'))?this.$route.query.product:0,
},
paginator: [],
},
};
},
created() {
// When the component is created, check to see if there is an Items Per Page
// setting or a page number in the URL, if not, default those $route parameters
// manually as follows.
if (!('ipp' in this.$route.query)) {
// Set the $route Items per Page to the this.page.filters.ipp value
this.$route.query.ipp = this.page.filters.ipp;
}
if (!('page' in this.$route.query)) {
// Default to page 1, if page is not defined, then it is the first page of results
this.$route.query.page = 1;
}
if (!('product' in this.$route.query)) {
// Default to page 1, if page is not defined, then it is the first page of results
this.$route.query.product = 0;
}
},
mounted() {
// Get the category/name from the end of the path
const type = this.$route.params.category;
// Set Video Type Attributes
const types = {
products: {
id: 'products',
name: 'Corporate Products',
},
android: {
id: 'android',
name: 'Android',
},
ios: {
id: 'ios',
name: 'iOS',
},
windows: {
id: 'windows',
name: 'Windows',
},
'cross-device': {
id: 'cross-device',
name: 'Cross-Device',
},
'processes-and-tools': {
id: 'Processes and Tools',
name: 'Processes and Tools',
},
all: {
id: 'all',
name: 'All Videos',
},
};
// Check if the supplied value is in the allowed values
if (type in types) {
// Put the Page information into a DOM accessible array
this.page.data = types[type];
// If they need all Videos, call getRecentVideos
if (type === 'all') {
this.getRecentVideos(this.page.filters.ipp, this.$route.query.page, this.page.filters.product);
} else {
// Gets the videos by category (type) and amount
this.getVideosByCategory(this.page.data.id, this.page.filters.ipp, this.$route.query.page, this.page.filters.product);
}
} else {
// If it's not a valid category, send an error 404 message
window.location = 'https://clpstaging.mcafee.com/error';
}
},
watch: {
// Watch for the Items Per Page selection to change
ipp(val) {
// If they need all Videos, call getRecentVideos
if (this.page.data.id === 'all') {
this.getRecentVideos(val, this.$route.query.page, this.page.filters.product);
} else {
// Reload the component
this.$route.query.ipp = val;
this.getVideosByCategory(this.page.data.id, val, this.$route.query.page, this.page.filters.product);
}
},
// Watch for changes to the page number
pagenum(val) {
// If they need all Videos, call getRecentVideos
if (this.page.data.id === 'all') {
this.getRecentVideos(this.page.filters.ipp, val, this.page.filters.product);
} else {
// Reload the component
this.$route.query.page = val;
this.getVideosByCategory(this.page.data.id, this.$route.query.ipp, val, this.page.filters.product);
}
},
// Watch for changes to the product filter
productFilter(val) {
// If they need all Videos, call getRecentVideos
if (this.page.data.id === 'all') {
this.getRecentVideos(this.page.filters.ipp, this.$route.query.page, val);
} else {
// Reload the component
this.$route.query.product = val;
this.getVideosByCategory(this.page.data.id, this.$route.query.ipp, this.$route.query.page, val);
}
}
},
computed: {
// Define the function that chunks the results to build a
// responsive layout.
videoChunks() {
return _.chunk(this.videos, 2);
},
// Define the Items-Per-Page value for the Watcher
// This ensures the data is updated when a user makes a change
// to Items-Per-Page filter.
ipp() {
return this.page.filters.ipp;
},
// Define the paginator value
paginate() {
return this.page.paginator;
},
// Define the pagenum value for the Watcher.
// This ensures that the component is reloaded
// when the users makes a selection from the paginator.
pagenum() {
return (this.$route.query.page === 'undefined')?1:this.$route.query.page;
},
productFilter() {
return this.page.filters.product;
},
},
methods: {
// Methods that get called upon mount. See Vue component lifecycle.
async getVideosByCategory(category, amount, pagenumber, productId) {
// Build filters
await this.getProducts();
// Wait for the API to send back a response. await keyword only works in async functions
const response = await TestService.fetchVideosByCategory(category, amount, pagenumber, productId);
// Total number of results
this.page.data.total = response.data[1][0].total;
// Set total number of pages based on Items per Page
this.page.data.pages = Math.ceil(response.data[1][0].total / this.page.filters.ipp);
// Set the videos object to the first object (the array of videos we want)
// of the JSON response from the API
this.videos = response.data[0];
// Add a new level of history without reloading the page with the udpated filters
// And set the props to match
// If the current url in the address bar is different from the query that
// would generate the data on the page
if (`${this.$route.path}?ipp=${amount}&page=${pagenumber}&product=${productId}` != this.$route.fullPath) {
history.pushState(this.page, 'Example Site', `${this.$route.path}?ipp=${amount}&page=${pagenumber}&product=${productId}`);
this.$route.query.page = pagenumber;
this.page.filters.page = pagenumber;
this.$route.query.ipp = amount;
this.page.filters.ipp = amount;
this.$route.query.product = productId;
this.page.filters.product = productId;
}
// Add a new level of history without reloading the page with the udpated filters
// And set the props to match
// If the selected filters result in no results found
if (this.page.data.pages === 0) {
history.pushState(this.page, 'Example Site', `${this.$route.path}?ipp=${amount}&page=1&product=${productId}`);
this.$route.query.page = 1;
this.page.filters.page = 1;
this.$route.query.ipp = amount;
this.page.filters.ipp = amount;
this.$route.query.product = productId;
this.page.filters.product = productId;
}
// Check to make sure that the user isn't beyond the last page of results.
// If they are, redirect them to the last page of results.
// When updating filters, it's possible for a user to set a filter while on page 10,
// But the results would only fill 7 pages. The user would be redirected to page 7 with
// the same filters.
if (this.page.data.pages < this.$route.query.page && this.page.data.pages != 0) {
let redir = '';
for (const key in this.page.filters) {
redir = `${redir}&${key}=${this.page.filters[key]}`;
}
redir = redir.replace(/^&/g, '?').replace(/page=[0-9]*/g, `page=${this.page.data.pages}`);
window.location = redir;
}
// build paginator
await this.paginator(this.page.data.total, this.page.data.pages, this.$route.query.page);
},
async getRecentVideos(amount, pagenumber, productId) {
// Build filters
await this.getProducts();
// Wait for the API to send back a response. await keyword only works in async functions
const response = await TestService.fetchVideos(amount, pagenumber, productId);
// Total number of results
this.page.data.total = response.data[1][0].total;
// Set total number of pages based on Items per Page
this.page.data.pages = Math.ceil(response.data[1][0].total / this.page.filters.ipp);
// Set the videos object to the first object (the array of videos we want)
// of the JSON response from the API
this.videos = response.data[0];
// Add a new level of history without reloading the page with the udpated filters
// And set the props to match
// If the current url in the address bar is different from the query that
// would generate the data on the page
if (`${this.$route.path}?ipp=${amount}&page=${pagenumber}&product=${productId}` != this.$route.fullPath) {
history.pushState(this.page, 'Example Site', `${this.$route.path}?ipp=${amount}&page=${pagenumber}&product=${productId}`);
this.$route.query.page = pagenumber;
this.page.filters.page = pagenumber;
this.$route.query.ipp = amount;
this.page.filters.ipp = amount;
this.$route.query.product = productId;
this.page.filters.product = productId;
}
// Add a new level of history without reloading the page with the udpated filters
// And set the props to match
// If the selected filters result in no results found
if (this.page.data.pages === 0) {
history.pushState(this.page, 'Example Site', `${this.$route.path}?ipp=${amount}&page=1&product=${productId}`);
this.$route.query.page = 1;
this.page.filters.page = 1;
this.$route.query.ipp = amount;
this.page.filters.ipp = amount;
this.$route.query.product = productId;
this.page.filters.product = productId;
}
// Check to make sure that the user isn't beyond the last page of results.
// If they are, redirect them to the last page of results.
// When updating filters, it's possible for a user to set a filter while on page 10,
// But the results would only fill 7 pages. The user would be redirected to page 7 with
// the same filters.
if (this.page.data.pages < this.$route.query.page && this.page.data.pages != 0) {
let redir = '';
for (const key in this.page.filters) {
redir = `${redir}&${key}=${this.page.filters[key]}`;
}
redir = redir.replace(/^&/g, '?').replace(/page=[0-9]* /g, `page=${this.page.data.pages}`);
window.location = redir;
}
// build paginator
await this.paginator(this.page.data.total, this.page.data.pages, this.$route.query.page);
},
async getProducts() {
// Fetch the list of products
const response = await TestService.fetchProducts();
// Set the response to a variable
let out = response.data;
// Unshift the array and add a default "All" products option to the top
out.unshift({product_name: 'All',tid: 0,});
this.page.data.products = out;
},
async paginator(total, pages, thisPage) {
// Find out where to start the Paginator at.
// Set the start variable
var start = 0;
if (Number(thisPage) <= 5) {
// If the user is looking at page 5 or less, start the count at 1
start = 1;
} else {
// If the user is looking at a page higher than 5, check to see if the
// user is on a page 5 or less away from the last page.
if (Number(thisPage)+5 > pages) {
// If the current page is 5 or less away from the last page,
// we need to make sure that the navigation stays visually similar
// by making sure that the same number of pages remain in the paginator.
// Do this by the following equation where:
// c = current page Number
// t = total number of pages
// c - ( 10 - ( t - c ) )
start = Number(thisPage)-(10-(pages-Number(thisPage)));
} else {
// If the current page is more than 5 away from the last page,
// just start at 5 before the current page.
start = Number(thisPage)-5;
}
}
// set the end variable
var end = 0;
// Check if the current page is 5 or less away from the last page.
if (Number(thisPage)+5 > pages) {
// If the current page number is 5 or less away from the last page,
// set it to to the number of the last page.
end = pages;
} else {
// If the current page is more than 5 away from the last page,
// check to see if the current page is 5 or less away from the
// first page.
if (Number(thisPage) <= 5) {
// If the current page is 5 away or closer to the first page,
// we need to make sure that the navigation stays visually similar
// by making sure that the same number of pages remain in the paginator.
// Do this by the following equation where:
// c = current page Number
// c + ( 10 - c )
end = Number(thisPage)+(11-Number(thisPage));
} else {
// If the current page is more than 5 away from the first page,
// end 5 after current page. It's already been checked that
// the current page is more than 5 away from the last page.
end = Number(thisPage)+5;
}
}
// Set an array to hold the page numbers
var pageArr = [];
// Count the line numbers and push them into the array
for (var count = start; count <= end; count++) {
pageArr.push(count);
}
// Set the paginator numbers into the DOM
this.page.paginator = pageArr;
},
},
};
</script>
<style lang="scss">
@import '../assets/scss/_colors.scss';
.paginator {
div {
list-style-type:none;
padding:0rem;
display:flex;
flex-flow:nowrap;
justify-content:space-around;
.router-link-active {
display:inline-block;
width:100%;
color:$darkGray;
padding: 0.5rem 0rem;
border-top:solid $lightGray 0.2rem;
font-size: 1.6rem;
font-weight:bold;
text-decoration:none;
&.disabled {
color: $lightGray;
&:hover {
border-top: solid $lightGray 0.2rem;
cursor:default;
}
}
&.router-link-exact-active {
border-top:solid $mcafeeRed 0.2rem;
}
&:hover {
border-top:solid $mcafeeRed 0.2rem;
}
}
}
}
</style>
<template>
<b-container>
<b-row class="w-100">
<b-col md="12" lg="12" xl="12" class="paginator">
<div v-model="paginate">
<router-link
v-if="$route.query.page > 1"
:to="{ name: $route.name, query: { ipp: page.filters.ipp, page: Number($route.query.page) - 1, product: page.filters.product} }"
class="prev">< Previous</router-link>
<div
v-else
class="prev disabled router-link-active">< Previous</div>
<router-link v-for="pages in paginate"
v-bind:key = "pages"
:to="{ name: $route.name, query: { ipp: page.filters.ipp, page: pages, product: page.filters.product} }">{{ pages }}</router-link>
<router-link
v-if="page.data.pages > $route.query.page"
:to="{ name: $route.name, query: { ipp: page.filters.ipp, page: Number($route.query.page) + 1, product: page.filters.product} }"
class="next">Next ></router-link>
<div
v-else
class="next disabled router-link-active">Next ></div>
</div>
</b-col>
</b-row>
</b-container>
</template>