Reference Source

src/util/imageutility.js

import { BIKE_PHOTO_ENTRIES, PROFILE_PHOTO_ENTRIES, BIKE_DEFAULT_IMAGE, PROFILE_DEFAULT_IMAGE } from '../assets/static/entries';

/**
 * Image utility class for helping with image handling. 
 */
class ImageUtility {

	/**
	 * Checks the number of defaults with the length of the uploaded images and the allowed number of images.
	 *
	 * @param {string} type - The type of image constant requested (e.g. BIKE, PROFILE, etc.)
	 * @param {Number} num_defaults - The number of defaults found
	 * @param {List} uploaded_images - The list of uploaded images
	 * @return {Boolean} true: If the number of defaults found is conversely related to the number of uploaded images based on the allowed number of images; false: otherwise
	 */
	checkNumDefaults(type, num_defaults, uploaded_images) {
		 return (this.getTypeConstant(type, TYPE_CONSTANTS.indices.NUMBER_OF_IMAGES)-num_defaults === uploaded_images.length);
	}

	/**
	 * Checks if an image has already been uploaded by checking if it contains the firebase url.
	 *
	 * @param {string} image - An image url to check. Might be an object if image is trying to be uploaded
	 * @return {Boolean} true: If the image has already been uploaded; false: otherwise
	 */
	isAlreadyUploaded(image) {
		return image.hasOwnProperty('uri') ? false : image.startsWith(FIREBASE_URL);
	}

	/**
	 * Returns the possible image types.
	 *
	 * @return {Object} An object of strings
	 */
	getTypes() {
		return TYPE_NAMES;
	}

	/**
	 * Returns the constant associated with a particular image type and index.
	 *
	 * @param {string} type - The type of image constant requested (e.g. BIKE, PROFILE, etc.)
	 * @param {Number} index - The index of the constant in TYPE_CONSTANTS
	 * @return {string/Number} The constant associated with the type and index
	 */
	getTypeConstant(type, index) {
		return TYPE_CONSTANTS[type][index];
	}

	/**
	 * Checks if the image is the default image for an associated type.
	 *
	 * @param {string} type - The type of image constant requested (e.g. BIKE, PROFILE, etc.)
	 * @param {string} image - The url to an image
	 * @return {Boolean} true: if the image is the default image; false: otherwise
	 */
	isDefaultImage(type, image) {
		return image === this.getTypeConstant(type, TYPE_CONSTANTS.indices.DEFAULT_IMAGE);
	}

	/**
	 * Returns the default image for a specific image type.
	 *
	 * @param {string} type - The type of image constant requested (e.g. BIKE, PROFILE, etc.)
	 * @return {string} The default image for the image type
	 */	
	getDefaultImage(type) {
		return this.getTypeConstant(type, TYPE_CONSTANTS.indices.DEFAULT_IMAGE);
	}

	/**
	 * Returns the photo entries.

	 * @param {string} type - The type of image constant requested (e.g. BIKE, PROFILE, etc.)
	 * @return {Object} The photo entries
	 */
	getPhotoEntries(type) {
		return this.getTypeConstant(type, TYPE_CONSTANTS.indices.PHOTO_ENTRIES);
	}

	/**
	 * Checks whether the image list is valid using an overly complex set of logical comparisons.
	 * Really not needed but all these cases came up and proved to be a problem.
	 *
	 * @param {List} imagelist - A list of images to check
	 * @return {Boolean} true: If valid; false: otherwise 
	 */
	checkImageListValid(imagelist) {
		return (typeof imagelist !== 'undefined' && imagelist != undefined && imagelist != null && imagelist != [] && imagelist.length !== 0);
	}

	/**
	 * Returns the defined file extension for images.
	 *
	 * @return {string} The file extension (default '.jpg')
	 */
	getFileExtension() {
		return FILE_EXTENSION;
	}

	/**
	 * Checks if all the images are default images.
	 *
	 * @param {string} type - The type of image constant requested (e.g. BIKE, PROFILE, etc.)
	 * @param {List} images - A list of images
	 * @return {Boolean} true: if all the images are the default image; false: if any one of them is not
	 */
	checkPhotosForDefaults(type, images) {
		let all_defaults = true;
		for (let i=0; i < images.length; i++) {
			// AND the validity of the image with the previous result
			all_defaults &= (images[i].illustration === this.getTypeConstant(type, TYPE_CONSTANTS.indices.DEFAULT_IMAGE) || images[i].illustration == undefined);
		}
		
		return !!all_defaults; // !! converts to boolean, needed to convert number to actual boolean value because errors occurred
	}


	/**
	 * Forms the thumbnail into a useable list of objects.
	 * 
	 * @param {List} thumbnails - A list of thumbnails with links
	 * @return {List} A list of thumbnail objects with an 'illustration' property
	 */
	formThumbnail(thumbnails) {
		let formedThumbnails = [];
		if (thumbnails != undefined) {
			for (let i=0; i < thumbnails.length; i++) {
				// Need to form the thumbnail property for the carousel
				formedThumbnails.push({illustration: thumbnails[i]});
			}
		}
		return formedThumbnails;
	}

	/**
	 * Add remaining defaults to the list of thumbnails for editing purposes.
	 *
	 * @param {string} type - The type of image constant requested (e.g. BIKE, PROFILE, etc.)
	 * @param {List} thumbnails - A list of thumbnails
	 * @return {List} A list of thumbnails of length NUMBER_OF_BIKE_IMAGES with defaults
	 */
	addRemainingDefaults(type, thumbnails) {
		// Number of defaults remaining is the number of images the type allows minus the number of provided images
		const defaults_remaining = this.getTypeConstant(type, TYPE_CONSTANTS.indices.NUMBER_OF_IMAGES) - thumbnails.length;
		const default_thumbnail = {illustration: this.getTypeConstant(type, TYPE_CONSTANTS.indices.DEFAULT_IMAGE)};
		for (let i=0; i < defaults_remaining; i++) {
			thumbnails.push(default_thumbnail);
		}
		return thumbnails;
	}

	/**
	 * Return the default photo entries.
	 *
	 * @param {string} type - The type of image constant requested (e.g. BIKE, PROFILE, etc.)
	 * @return {List} A list of objects with the property 'illustration' that contains the uri
	 */
	getDefaultPhotos(type) {
		return JSON.parse(JSON.stringify(this.getPhotoEntries(type)));
	}
}

const FILE_EXTENSION = '.jpg';
const FIREBASE_URL = 'https://firebasestorage.googleapis.com';
const NUMBER_OF_BIKE_IMAGES = BIKE_PHOTO_ENTRIES.length;
const NUMBER_OF_PROFILE_IMAGES = PROFILE_PHOTO_ENTRIES.length;

// Constant corresponding to property names in the TYPE_CONSTANTS object
const TYPE_NAMES = {
	BIKE: 'BIKE',
	PROFILE: 'PROFILE'
}
/*
 * The purpose of this data structure is to keep track of all the constants for different image types.
 * Different MVP components need different default images and number of images so this way we can keep track
 * of them all and keep our functions generalized.
 * To add another image type, add the name to the TYPE_NAMES object, add the corresponding string as a property
 * value in the TYPE_CONSTANTS structure and a list of the constants. Keep the list of the constants in the same
 * order as the indices indicate in the 'indices' property below.
 */
const TYPE_CONSTANTS = {
	BIKE: [
		BIKE_PHOTO_ENTRIES,
		BIKE_DEFAULT_IMAGE,
		NUMBER_OF_BIKE_IMAGES
	],
	PROFILE: [
		PROFILE_PHOTO_ENTRIES,
		PROFILE_DEFAULT_IMAGE,
		NUMBER_OF_PROFILE_IMAGES
	],
	indices: {
		PHOTO_ENTRIES: 0,
		DEFAULT_IMAGE: 1,
		NUMBER_OF_IMAGES: 2
	}
}

const ImageUtil = new ImageUtility();
export default ImageUtil;