<commit_before>'use strict';

/* jasmine specs for models go here */

describe("Mechello Models", function () {
    var $scope;

    beforeEach(inject(function ($rootScope) {
        $scope = $rootScope.$new();
    }));

    describe("Product.Models.ProductAttribute", function () {
        it("Should create an empty product attribute if there is not productAttributeFromServer", function () {
            var productatt = new merchello.Models.ProductAttribute();
            expect(productatt.key).toBe("");
        });
        it("Should create an populated product attribute if there is a productAttributeFromServer", function () {
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            var productatt = new merchello.Models.ProductAttribute(pafs);
            expect(productatt.key).toBe("123");
            expect(productatt.optionKey).toBe("321");
            expect(productatt.name).toBe("bane");
            expect(productatt.sortOrder).toBe(6);
            expect(productatt.optionOrder).toBe(6);       //Possible Issue: Needs Review
            expect(productatt.isRemoved).toBe(false);   //Possible Issue: Needs Review
        });

        it("Should return the correct option out of a list of options.", function () {
            var options = [];
            for (var i in [1, 2, 3, 4, 5, 6, 7]) {
                var pofs = { key: i.toString(), name: "bane", required: "aye", sortOrder: 6 };
                //var productopt = new merchello.Models.ProductOption(pofs);
                options.push(pofs);
            }
            var pafs = { key: "123", optionKey: "6", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            var productatt = new merchello.Models.ProductAttribute(pafs);
            var option = productatt.findMyOption(options);
            expect(option).not.toBe(undefined);
            expect(option.key).toBe("6");
        });
    });

    describe("Product.Models.ProductOption", function () {
        var productopt;
        var pofs;

        beforeEach(function () {
            pofs = { key: "123", name: "bane", required: "aye", sortOrder: 6 };
            productopt = new merchello.Models.ProductOption(pofs);
        });

        it("Should create an empty product option if there is not productOptionFromServer", function () {
            productopt = new merchello.Models.ProductOption();
            expect(productopt.key).toBe("");
            expect(productopt.required).toBe("");
            expect(productopt.name).toBe("");
            expect(productopt.sortOrder).toBe(1);
            expect(productopt.choices.length).toBe(0);
        });
        it("Should create an populated product option if there is a productOptionFromServer", function () {
            expect(productopt.key).toBe("123");
            expect(productopt.required).toBe("aye");
            expect(productopt.name).toBe("bane");
            expect(productopt.sortOrder).toBe(6);
            expect(productopt.choices.length).toBe(0);
        });

        it("Should add a new choice", function () {
            productopt.addChoice("plane");
            expect(productopt.choices.length).toBe(1);
            expect(productopt.choices[0].sortOrder).toBe(productopt.choices.length);
            expect(productopt.choices[0].optionKey).toBe(productopt.key);
        });

        it("Should remove a choice", function () {
            productopt.addChoice("plane");
            var choice = productopt.removeChoice(0);
            expect(choice).not.toBe(undefined);
            expect(productopt.choices.length).toBe(0);
        });

        it("Should make the sortOrder sync with the order in the choices array", function () {
            productopt.addChoice("plane");
            productopt.choices[0].sortOrder += 3;
            productopt.addChoice("mane");
            productopt.choices[1].sortOrder += 2;
            productopt.addChoice("dane");
            productopt.choices[1].sortOrder += 1;

            productopt.resetChoiceSortOrder();
            for (var i = 0; i < productopt.choices.length; i++) {
                expect(productopt.choices[i].sortOrder).toBe(i + 1);
            }

        });

        it("Should check if this choice exists in my choices array", function () {
            productopt.addChoice("plane");
            productopt.choices[0].key = "321"
            var choice = productopt.choices[0];
            productopt.addChoice("fame");
            productopt.choices[1].key = "123"
            var exists = productopt.choiceExists(choice);
            expect(exists).toBe(true);
        });

        it("Should find a choice by name and return it or undefined if not found", function () {
            productopt.addChoice("plane");
            productopt.choices[0].key = "321"
            productopt.addChoice("fame");
            productopt.choices[1].key = "123"
            var choice = productopt.findChoiceByName("plane");
            expect(choice).not.toBe(undefined);
            choice = productopt.findChoiceByName("main");
            expect(choice).toBe(undefined);
        });
    });

    describe("Product.Models.ProductVariant", function () {
        var productvar;
        var pvfs;

        beforeEach(function () {
            var pofs = { key: "123", name: "bane", required: "aye", sortOrder: 6 };
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            pvfs = {
                key: "123",
                name: "bane",
                productKey: "asdfg",
                sku: "1qa2ws",
                price: 1.00,
                costOfGoods: 2.00,
                salePrice: 3.00,
                onSale: true,
                manufacturer: "Me",
                manufacturerModelNumber: "1234567890",
                weight: 10,
                length: 11,
                width: 12,
                height: 13,
                barcode: "10101010",
                available: false,
                trackInventory: true,
                outOfStockPurchase: true,
                taxable: true,
                shippable: true,
                download: true,
                downloadMediaId: 123890,
                totalInventoryCount: 1000000000,
                attributes : [pafs, pafs],
                attributeKeys: ["123"],
                catalogInventories: []
            };

            productvar = new merchello.Models.ProductVariant(pvfs);
        });

        it("should create an empty product variant", function () {
            productvar = new merchello.Models.ProductVariant();
            expect(productvar).not.toBe(undefined);
            expect(productvar.attributes.length).toBe(0);
            expect(productvar.selected).toBe(false);
            expect(productvar.key).toBe("");
            expect(productvar.name).toBe("");
        });

        it("should create an filled product variant", function () {
            expect(productvar).not.toBe(undefined);
            expect(productvar.attributes.length).toBe(2);
            expect(productvar.catalogInventories.length).toBe(0);
            expect(productvar.selected).toBe(false);
            expect(productvar.key).toBe("123");
            expect(productvar.name).toBe("bane");
        });

        it("should copy from product to create a master variant", function () {
            expect(productvar).not.toBe(undefined);
            var p = { key: "234", name: "same", catalogInventories: [] };
            productvar.copyFromProduct(p);
            expect(productvar.attributes.length).toBe(0);
            expect(productvar.catalogInventories.length).toBe(0);
            expect(productvar.selected).toBe(false);
            expect(productvar.key).toBe("123");
            expect(productvar.productKey).toBe("234");
            expect(productvar.name).toBe("same");
        });

        it("should fix attribute sort orders", function () {
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            var pofs = { key: "123", name: "bane", required: "aye", sortOrder: 6 };
            var options = [];
            for (var i in [1, 2, 3, 4]) {
                pofs.sortorder = i + 1;
                pafs.optionorder = 4 - i + 1;
                pafs.key += i.toString();
                pafs.name += i.toString();
                options.push(new merchello.Models.ProductOption(pofs));
                productvar.attributes.push(new merchello.Models.ProductAttribute(pafs));
            }
            productvar.fixAttributeSortOrders()
            for (var i in productvar.attributes) {
                expect(i.optionOrder).toBe(i.sortOrder);
            }
        });

        it("should add Attributes As Properties for sorting in a table", function () {
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            var pofs = { key: "123", name: "bane", required: "aye", sortOrder: 6 };
            var options = [];
            productvar = new merchello.Models.ProductVariant();

            for (var i in [1, 2, 3, 4]) {
                pofs.sortorder = i + 1;
                pafs.optionorder = 4 - i + 1;
                pofs.key = i.toString();
                pofs.name += i.toString();

                pafs.optionKey = i.toString();
                pafs.name += i.toString();
                options.push(new merchello.Models.ProductOption(pofs));
                productvar.attributes.push(new merchello.Models.ProductAttribute(pafs));
            }
            productvar.addAttributesAsProperties(options);

            _.each(options, function (i) {
                expect(productvar[i.name]).not.toBe(undefined);
            });
        });

        it("should return if it isComposedFromAttribute", function () {
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            productvar.attributes.push(pafs);
            expect(productvar.isComposedFromAttribute(pafs)).toBe(true);
            var new_pafs = _.extend({}, pafs);
            new_pafs.key = "###";
            expect(productvar.isComposedFromAttribute(new_pafs)).toBe(false);
        });

        it("should ensure the catalog inventory", function () {
            var warehouse = { key: "meh", warehouseCatalogs: [{key: "123", name: "Matt"}] };
            expect(productvar.catalogInventories.length).toBe(0);
            productvar.ensureCatalogInventory(warehouse);
            expect(productvar.catalogInventories.length).toBe(1);
            productvar.ensureCatalogInventory(warehouse);
            expect(productvar.catalogInventories.length).toBe(1);
        });

        it("should add a variant to this product", function () {
            var warehouse = { key: "meh", warehouseCatalogs: [{ key: "123", name: "Matt" }] };
            productvar.addCatalogInventory(warehouse);
            expect(productvar.catalogInventories.length).toBe(1);
            expect(productvar.catalogInventories[0].productVariantKey).toBe(productvar.key);
            expect(productvar.catalogInventories[0].warehouseKey).toBe(warehouse.key);
            expect(productvar.catalogInventories[0].catalogKey).toBe("123");
            expect(productvar.catalogInventories[0].catalogName).toBe("Matt");
        });

        it("should update the global inventory on change", function () {
            productvar.globalInventoryChanged(5);
            expect(productvar.totalInventoryCount).toBe(productvar.catalogInventories * 5);
            _.each(productvar.catalogInventories, function (i) {
                expect(i.count).toBe(5);
            });
        });
    });
});<commit_msg>Finished product model spec.<commit_after>'use strict';

/* jasmine specs for models go here */

describe("Mechello Models", function () {
    var $scope;

    beforeEach(inject(function ($rootScope) {
        $scope = $rootScope.$new();
    }));

    describe("Product.Models.ProductAttribute", function () {
        it("Should create an empty product attribute if there is not productAttributeFromServer", function () {
            var productatt = new merchello.Models.ProductAttribute();
            expect(productatt.key).toBe("");
        });
        it("Should create an populated product attribute if there is a productAttributeFromServer", function () {
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            var productatt = new merchello.Models.ProductAttribute(pafs);
            expect(productatt.key).toBe("123");
            expect(productatt.optionKey).toBe("321");
            expect(productatt.name).toBe("bane");
            expect(productatt.sortOrder).toBe(6);
            expect(productatt.optionOrder).toBe(6);       //Possible Issue: Needs Review
            expect(productatt.isRemoved).toBe(false);   //Possible Issue: Needs Review
        });

        it("Should return the correct option out of a list of options.", function () {
            var options = [];
            for (var i in [1, 2, 3, 4, 5, 6, 7]) {
                var pofs = { key: i.toString(), name: "bane", required: "aye", sortOrder: 6 };
                //var productopt = new merchello.Models.ProductOption(pofs);
                options.push(pofs);
            }
            var pafs = { key: "123", optionKey: "6", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            var productatt = new merchello.Models.ProductAttribute(pafs);
            var option = productatt.findMyOption(options);
            expect(option).not.toBe(undefined);
            expect(option.key).toBe("6");
        });
    });

    describe("Product.Models.ProductOption", function () {
        var productopt;
        var pofs;

        beforeEach(function () {
            pofs = { key: "123", name: "bane", required: "aye", sortOrder: 6 };
            productopt = new merchello.Models.ProductOption(pofs);
        });

        it("Should create an empty product option if there is not productOptionFromServer", function () {
            productopt = new merchello.Models.ProductOption();
            expect(productopt.key).toBe("");
            expect(productopt.required).toBe("");
            expect(productopt.name).toBe("");
            expect(productopt.sortOrder).toBe(1);
            expect(productopt.choices.length).toBe(0);
        });
        it("Should create an populated product option if there is a productOptionFromServer", function () {
            expect(productopt.key).toBe("123");
            expect(productopt.required).toBe("aye");
            expect(productopt.name).toBe("bane");
            expect(productopt.sortOrder).toBe(6);
            expect(productopt.choices.length).toBe(0);
        });

        it("Should add a new choice", function () {
            productopt.addChoice("plane");
            expect(productopt.choices.length).toBe(1);
            expect(productopt.choices[0].sortOrder).toBe(productopt.choices.length);
            expect(productopt.choices[0].optionKey).toBe(productopt.key);
        });

        it("Should remove a choice", function () {
            productopt.addChoice("plane");
            var choice = productopt.removeChoice(0);
            expect(choice).not.toBe(undefined);
            expect(productopt.choices.length).toBe(0);
        });

        it("Should make the sortOrder sync with the order in the choices array", function () {
            productopt.addChoice("plane");
            productopt.choices[0].sortOrder += 3;
            productopt.addChoice("mane");
            productopt.choices[1].sortOrder += 2;
            productopt.addChoice("dane");
            productopt.choices[1].sortOrder += 1;

            productopt.resetChoiceSortOrder();
            for (var i = 0; i < productopt.choices.length; i++) {
                expect(productopt.choices[i].sortOrder).toBe(i + 1);
            }

        });

        it("Should check if this choice exists in my choices array", function () {
            productopt.addChoice("plane");
            productopt.choices[0].key = "321"
            var choice = productopt.choices[0];
            productopt.addChoice("fame");
            productopt.choices[1].key = "123"
            var exists = productopt.choiceExists(choice);
            expect(exists).toBe(true);
        });

        it("Should find a choice by name and return it or undefined if not found", function () {
            productopt.addChoice("plane");
            productopt.choices[0].key = "321"
            productopt.addChoice("fame");
            productopt.choices[1].key = "123"
            var choice = productopt.findChoiceByName("plane");
            expect(choice).not.toBe(undefined);
            choice = productopt.findChoiceByName("main");
            expect(choice).toBe(undefined);
        });
    });

    describe("Product.Models.ProductVariant", function () {
        var productvar;
        var pvfs;

        beforeEach(function () {
            var pofs = { key: "123", name: "bane", required: "aye", sortOrder: 6 };
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            pvfs = {
                key: "123",
                name: "bane",
                productKey: "asdfg",
                sku: "1qa2ws",
                price: 1.00,
                costOfGoods: 2.00,
                salePrice: 3.00,
                onSale: true,
                manufacturer: "Me",
                manufacturerModelNumber: "1234567890",
                weight: 10,
                length: 11,
                width: 12,
                height: 13,
                barcode: "10101010",
                available: false,
                trackInventory: true,
                outOfStockPurchase: true,
                taxable: true,
                shippable: true,
                download: true,
                downloadMediaId: 123890,
                totalInventoryCount: 1000000000,
                attributes : [pafs, pafs],
                attributeKeys: ["123"],
                catalogInventories: []
            };

            productvar = new merchello.Models.ProductVariant(pvfs);
        });

        it("should create an empty product variant", function () {
            productvar = new merchello.Models.ProductVariant();
            expect(productvar).not.toBe(undefined);
            expect(productvar.attributes.length).toBe(0);
            expect(productvar.selected).toBe(false);
            expect(productvar.key).toBe("");
            expect(productvar.name).toBe("");
        });

        it("should create an filled product variant", function () {
            expect(productvar).not.toBe(undefined);
            expect(productvar.attributes.length).toBe(2);
            expect(productvar.catalogInventories.length).toBe(0);
            expect(productvar.selected).toBe(false);
            expect(productvar.key).toBe("123");
            expect(productvar.name).toBe("bane");
        });

        it("should copy from product to create a master variant", function () {
            expect(productvar).not.toBe(undefined);
            var p = { key: "234", name: "same", catalogInventories: [] };
            productvar.copyFromProduct(p);
            expect(productvar.attributes.length).toBe(0);
            expect(productvar.catalogInventories.length).toBe(0);
            expect(productvar.selected).toBe(false);
            expect(productvar.key).toBe("123");
            expect(productvar.productKey).toBe("234");
            expect(productvar.name).toBe("same");
        });

        it("should fix attribute sort orders", function () {
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            var pofs = { key: "123", name: "bane", required: "aye", sortOrder: 6 };
            var options = [];
            for (var i in [1, 2, 3, 4]) {
                pofs.sortorder = i + 1;
                pafs.optionorder = 4 - i + 1;
                pafs.key += i.toString();
                pafs.name += i.toString();
                options.push(new merchello.Models.ProductOption(pofs));
                productvar.attributes.push(new merchello.Models.ProductAttribute(pafs));
            }
            productvar.fixAttributeSortOrders()
            for (var i in productvar.attributes) {
                expect(i.optionOrder).toBe(i.sortOrder);
            }
        });

        it("should add Attributes As Properties for sorting in a table", function () {
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            var pofs = { key: "123", name: "bane", required: "aye", sortOrder: 6 };
            var options = [];
            productvar = new merchello.Models.ProductVariant();

            for (var i in [1, 2, 3, 4]) {
                pofs.sortorder = i + 1;
                pafs.optionorder = 4 - i + 1;
                pofs.key = i.toString();
                pofs.name += i.toString();

                pafs.optionKey = i.toString();
                pafs.name += i.toString();
                options.push(new merchello.Models.ProductOption(pofs));
                productvar.attributes.push(new merchello.Models.ProductAttribute(pafs));
            }
            productvar.addAttributesAsProperties(options);

            _.each(options, function (i) {
                expect(productvar[i.name]).not.toBe(undefined);
            });
        });

        it("should return if it isComposedFromAttribute", function () {
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            productvar.attributes.push(pafs);
            expect(productvar.isComposedFromAttribute(pafs)).toBe(true);
            var new_pafs = _.extend({}, pafs);
            new_pafs.key = "###";
            expect(productvar.isComposedFromAttribute(new_pafs)).toBe(false);
        });

        it("should ensure the catalog inventory", function () {
            var warehouse = { key: "meh", warehouseCatalogs: [{key: "123", name: "Matt"}] };
            expect(productvar.catalogInventories.length).toBe(0);
            productvar.ensureCatalogInventory(warehouse);
            expect(productvar.catalogInventories.length).toBe(1);
            productvar.ensureCatalogInventory(warehouse);
            expect(productvar.catalogInventories.length).toBe(1);
        });

        it("should add a variant to this product", function () {
            var warehouse = { key: "meh", warehouseCatalogs: [{ key: "123", name: "Matt" }] };
            productvar.addCatalogInventory(warehouse);
            expect(productvar.catalogInventories.length).toBe(1);
            expect(productvar.catalogInventories[0].productVariantKey).toBe(productvar.key);
            expect(productvar.catalogInventories[0].warehouseKey).toBe(warehouse.key);
            expect(productvar.catalogInventories[0].catalogKey).toBe("123");
            expect(productvar.catalogInventories[0].catalogName).toBe("Matt");
        });

        it("should update the global inventory on change", function () {
            productvar.globalInventoryChanged(5);
            expect(productvar.totalInventoryCount).toBe(productvar.catalogInventories * 5);
            _.each(productvar.catalogInventories, function (i) {
                expect(i.count).toBe(5);
            });
        });
    });

    describe("Product.Models.Product", function () {
        var product;
        var pfs;

        beforeEach(function () {
            var pafs = { key: "123", optionKey: "321", name: "bane", sortOrder: 6, optionOrder: 7, isRemoved: true };
            var pofs = { key: "123", name: "bane", required: "aye", sortOrder: 6, choices: [_.extend({}, pafs), _.extend({}, pafs)] };
            var pofsv2 = { key: "321", name: "fame", required: "neh", sortOrder: 3, choices: [_.extend({}, pafs), _.extend({}, pafs)] };
            var pvfs = {
                key: "123",
                name: "bane",
                productKey: "asdfg",
                sku: "1qa2ws",
                price: 1.00,
                costOfGoods: 2.00,
                salePrice: 3.00,
                onSale: true,
                manufacturer: "Me",
                manufacturerModelNumber: "1234567890",
                weight: 10,
                length: 11,
                width: 12,
                height: 13,
                barcode: "10101010",
                available: false,
                trackInventory: true,
                outOfStockPurchase: true,
                taxable: true,
                shippable: true,
                download: true,
                downloadMediaId: 123890,
                totalInventoryCount: 1000000000,
                attributes: [pafs, pafs],
                attributeKeys: ["123"],
                catalogInventories: []
            };

            pfs = {
                key: "123",
                name: "bane",
                sku: "1qa2ws",
                price: 1.00,
                costOfGoods: 2.00,
                salePrice: 3.00,
                onSale: true,
                manufacturer: "Me",
                manufacturerModelNumber: "1234567890",
                weight: 10,
                length: 11,
                width: 12,
                height: 13,
                barcode: "10101010",
                available: false,
                trackInventory: true,
                outOfStockPurchase: true,
                taxable: true,
                shippable: true,
                download: true,
                downloadMediaId: 123890,
                hasOptions: true,
                hasVariants: true,
                productOptions: [pofs, pofsv2],
                productVariants: [pvfs, (pvfs.sortOrder = 9)]
            };
            product = new merchello.Models.Product(pfs, false);
        });

        it("should create a defined object", function () {
            expect(product).not.toBe(undefined);
            for (var i in pfs) {
                expect(product[i]).not.toBe(undefined);
            }

        });

        it("should create a empty object", function () {
            product = new merchello.Models.Product();

            expect(product.key).toBe("");
            expect(product.name).toBe("");
            expect(product.sku).toBe("");
            expect(product.price).toBe(0.00);
            expect(product.costOfGoods).toBe(0.00);
            expect(product.salePrice).toBe(0.00);
            expect(product.onSale).toBe(false);
            expect(product.manufacturer).toBe("");
            expect(product.manufacturerModelNumber).toBe("");
            expect(product.weight).toBe(0);
            expect(product.length).toBe(0);
            expect(product.width).toBe(0);
            expect(product.height).toBe(0);
            expect(product.barcode).toBe("");
            expect(product.available).toBe(true);
            expect(product.trackInventory).toBe(false);
            expect(product.outOfStockPurchase).toBe(false);
            expect(product.taxable).toBe(false);
            expect(product.shippable).toBe(false);
            expect(product.download).toBe(false);
            expect(product.downloadMediaId).toBe(-1);
            expect(product.hasOptions).toBe(false);
            expect(product.hasVariants).toBe(false);

            expect(product.productOptions.length).toBe(0);

            expect(product.productVariants.length).toBe(0);

            expect(product.catalogInventories.length).toBe(0);
        });

        it("should create a populated product but not map the children", function () {
            product = new merchello.Models.Product(pfs, true);
            expect(product.productOptions).toBe(undefined);
            expect(product.productVariants).toBe(undefined);
        });

        it("should add a blank options to the product", function () {
            product.productOptions = undefined;
            product.hasOptions = false;
            product.addBlankOption();
            expect(product.productOptions).not.toBe(undefined);
            expect(product.productOptions.length).toBe(1);
            expect(product.hasOptions).toBe(true);
            product.productOptions = [];
            product.addBlankOption();
            expect(product.productOptions.length).toBe(1);
            expect(product.productOptions[0].key).toBe("");
        });

        it("should remove an option from it's productOptions", function () {
            expect(product.productOptions.length).toBe(2);
            product.removeOption(product.productOptions[0]);
            expect(product.productOptions.length).toBe(1);
        });

        it("should create an array of all choices in a flattened list", function () {
            var flattenedlist = product.flattened();
            var choices = ["choice1", "choice2"];
            expect(flattenedlist.length).toBe(product.productOptions.length * 2);
            for (var i; i < flattenedlist.length; i++) {
                expect(flattenedlist[i]).toBe(choices[i % 2]);
            }
        });

        it("should add variant to the product", function () {
            var attrs = [{ one: "one", key: "one" }, { two: "two", key: "two" }];
            product.hasVariants = false;
            var vari = product.addVariant(attrs);
            expect(vari.name).toBe("");
            expect(vari.selected).toBe(true);
            expect(vari.sku).toBe("");
            expect(vari.attributeKeys.length).toBe(2);
            expect(product.productVariants.length).toBe(3);
            expect(product.hasVariants).toBe(true);
        });

        it("should remove variant to the product", function () {
            expect(product.productVariants.length).toBe(2);
            product.removeVariant(0);
            expect(product.productVariants.length).toBe(1);
            product.removeVariant(0);
            expect(product.productVariants.length).toBe(0);
        });

        it("should return the lowest variant price if the product has variants", function () {
            for(var i = 0; i < product.productVariants.length; i++) {
                product.productVariants[i].price = i+1;
            }
            expect(product.variantsMinimumPrice().price).toBe(1);
            product.productVariants = undefined;
            product.minPrice = { price: 1200 };
            expect(product.variantsMinimumPrice().price).toBe(1200);
        });

        it("should return the lowest variant price if the product has variants", function () {
            for (var i = 0; i < product.productVariants.length; i++) {
                product.productVariants[i].price = i + 1;
            }
            expect(product.variantsMaximumPrice().price).toBe(product.productVariants.length);
            product.productVariants = undefined;
            product.maxPrice = { price: 1200 };
            expect(product.variantsMaximumPrice().price).toBe(1200);
        });
    });
});<|endoftext|>


<commit_before>const dbConnection = require('../common/connection');
const util = require('util');
const query = util.promisify(dbConnection.query).bind(dbConnection);

const axios = require('axios');

class EducatorEntity {

    static async getUserInfoByToken(token) {
        try {
            const user = await axios({
                method: "get",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://www.googleapis.com/oauth2/v1/userinfo`
            })
            const userData = user.data;
            return userData;
        } catch (error) {
            console.log(error);
            //res.send('Invalid user').status(400);
        }
    }

    static async createPlaylist(body) {
        const sql = `INSERT INTO playlist (title,educatorId) VALUES ('${body.title}',${body.educatorId});`;
        console.log(sql);
        /* dbConnection.query(sql, function (err, result, fields) {
            return result;
        });*/
        const data = await query(sql);
        const lastRowId = await query(`SELECT * FROM playlist where playlistId=${data.insertId};`);
        console.log('last row id' + JSON.stringify(lastRowId));
        body.playlists.forEach(async (video) => {
            /*const insertQuery = `INSERT INTO video (videoId,playlistId,title,description,channelTitle,thumbnail,youtubeLink,duration) VALUES ('${video.videoId}',${lastRowId[0].playlistId},'${video.title}','${video.description}','${video.channelTitle}','${video.thumbnail}','${video.youtubeLink ? video.youtubeLink : null}','${video.duration}');`;
            dbConnection.query(insertQuery, function (err) {
                if (err) console.log('Insert video table:' + err)
            });*/

            var sql = "INSERT INTO video SET ?";
            // Connection attained as listed above.
            dbConnection.query(sql, {
                videoId: video.videoId, playlistId: video.playlistId, title: video.title,
                description: video.description, channelTitle: video.channelTitle, thumbnail: video.thumbnail, youtubeLink: video.youtubeLink ? video.youtubeLink : null, duration: video.duration
            }, function (err) {
                // check result if err is undefined.
                if (err) {
                    console.log('Insert video error:', err);
                }
            });

        })

        return lastRowId;
    }

    static async getAllVideos(playlistId) {
        dbConnection.query(`SELECT * FROM video where playlistId=${playlistId};`, function (err, result) {
            return result;
        });
    }

    static async getAllPlaylist() {
        const data = await query('SELECT * FROM playlist;');
        const respArray = [];
        for (let i = 0; i < data.length; i++) {
            const response = {
                playlistId: data[i].playlistId,
                title: data[i].title,
                videos: Object.values(JSON.parse(JSON.stringify(await this.getPlaylist(data[i].playlistId)))),
                count: Object.values(JSON.parse(JSON.stringify(await this.getPlaylist(data[i].playlistId)))).length
            }
            respArray.push(response);
        }

        return respArray;
    }

    static async getPlaylist(playlistId) {
        const data = await query(`SELECT * FROM video where playlistId=${playlistId};`);
        return data;
    }

    static async createEducator(body) {
        const sql = `INSERT INTO educators (email,firstName,lastName) VALUES ('${body.email}','${body.firstName}','${body.lastName}');`;
        console.log(sql);
        try {
            const data = await query(sql);
            return data;
        } catch (err) {
            if (err.code === 'ER_DUP_ENTRY') {
                return await query(`SELECT * FROM educators where email='${body.email}';`);
            }
            return err;
        }

    }

    static async assignTask(token, body) {
        try {
            const video = Object.values(JSON.parse(JSON.stringify(await query(`SELECT * FROM video where playlistId=${body.playlistId} LIMIT 1;`))));
            const result = await axios({
                method: "POST",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://classroom.googleapis.com/v1/courses/${body.courseId}/courseWork`,
                data: {
                    assigneeMode: "ALL_STUDENTS",
                    courseId: body.courseId,
                    title: body.taskName,
                    maxPoints: 100,
                    workType: "ASSIGNMENT",
                    state: "PUBLISHED",
                    materials: [
                        {
                            link: {
                                url: `${process.env.STD_PORTAL}?courseId=${body.courseId}&videoId=${video[0].videoId}`
                            }
                        }
                    ]
                }
            })

            console.log(result.data);
            body.classRoomTaskId = result.data.id;
        } catch (error) {
            console.log(error);
            return error.response.status;
            //res.send(error).status(400);
        }

        const sql = `INSERT INTO tasks(taskName,playlistId,courseId,studentId,classRoomTaskId) VALUES ('${body.taskName}',${body.playlistId},'${body.courseId}',${body.studentId ? body.studentId : null},'${body.classRoomTaskId}');`;
        console.log(sql);
        const data = await query(sql);

        const lastRowId = await query(`SELECT * FROM tasks where taskId=${data.insertId};`);
        body.taskId = lastRowId[0].taskId;
        const playlistId = body.playlistId;

        if (body.studentId && (body.courseId === null || body.courseId === undefined)) {
            body.status = 'NotStarted';
            await this.taskStatus(body);
        }
        if (body.courseId && (body.studentId === null || body.studentId === undefined)) {
            const students = await query(`SELECT * FROM students;`);
            dbConnection.query(
                'INSERT INTO tasks_status(taskId,studentId,status,courseId,classRoomTaskId) VALUES ?',
                [students.map(item => [body.taskId, item.studentId, 'NotStarted', body.courseId, body.classRoomTaskId])],
                (error) => {
                    console.log(error)
                }
            );

            const videos = Object.values(JSON.parse(JSON.stringify(await this.getPlaylist(playlistId))));
            for (let i = 0; i < videos.length; i++) {
                dbConnection.query(
                    'INSERT INTO student_analytics(videoId,studentId,videoStatus,videoProgress,playlistId,courseId,classRoomTaskId) VALUES ?',
                    [students.map(item => [videos[i].id, item.studentId, 'NotStarted', '00', playlistId, body.courseId, body.classRoomTaskId])],
                    (error) => {
                        console.log(error)
                    }
                );
            }
        }
        return data;
    }

    static async taskStatus(body) {
        if (body.status === 'NotStarted' || body.status === 'Inprogress' || body.status === 'Completed') {
            const sql = `INSERT INTO tasks_status(taskId,studentId,status) VALUES (${body.taskId},${body.studentId},'${body.status}');`;
            console.log(sql);
            const data = await query(sql);
            return data;
        } else {
            return {
                status: 400,
                reason: "Invalid task status"
            }
        }

    }

    static async updateTaskStatus(taskId, studentId, status) {
        if (status === 'NotStarted' || status === 'Inprogress' || status === 'Completed') {
            const sql = `UPDATE tasks_status SET status = '${status}' WHERE taskId = ${taskId} AND studentId = ${studentId};`;
            console.log(sql);
            const data = await query(sql);
            console.log(data);
            return data;
        } else {
            return {
                status: 400,
                reason: "Invalid task status"
            }
        }

    }

    static async addVideosToPlaylist(playlistId, body) {
        body.playlists.forEach((video) => {
            const insertQuery = `INSERT INTO video (videoId,playlistId,title,description,channelTitle,thumbnail,youtubeLink,duration) VALUES ('${video.videoId}',${playlistId},'${video.title}','${video.description}','${video.channelTitle}','${video.thumbnail}','${video.youtubeLink ? video.youtubeLink : null}','${video.duration}');`;
            dbConnection.query(insertQuery, function (err) {
                if (err) console.log('Insert video table:' + err)
            });
        })
        return await this.getPlaylist(playlistId);
    }

    static async getEducatorByEmail(email) {
        const sql = `SELECT * FROM educators where email = '${email}'`;
        console.log('query:', sql);
        const data = await query(sql);
        return data;
    }

    static async pullCourseDataFromClassRoomApi(token) {
        let courses;
        let userData;
        try {
            const result = await axios({
                method: "get",
                headers: { Authorization: `Bearer ${token}` },
                url: 'https://classroom.googleapis.com/v1/courses?courseStates=ACTIVE'
            })
            courses = result.data.courses;
        } catch (error) {
            console.log(error);
            return error.response.status;
            //res.send(error).status(400);
        }

        try {
            const user = await axios({
                method: "get",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://www.googleapis.com/oauth2/v1/userinfo`
            })
            userData = user.data;
        } catch (error) {
            console.log(error);
            //res.send('Invalid user').status(400);
        }

        await query(`DELETE FROM courses WHERE creator='${userData.email}';`);

        await query('INSERT INTO courses(courseId,name,descriptionHeading,ownerId,creator,courseState,creationTime) VALUES ?',
            [courses.map(item => [item.id, item.name, item.descriptionHeading, item.ownerId, userData.email, item.courseState, new Date(item.creationTime).toJSON().slice(0, 19).replace('T', ' ')])]);

        const result = await query(`SELECT * FROM courses WHERE creator='${userData.email}';`);
        return result;
    }

    static async invitation(token, body) {
        try {
            const result = await axios({
                method: "POST",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://classroom.googleapis.com/v1/invitations`,
                data: {
                    userId: body.studentId,
                    courseId: body.courseId,
                    role: 'STUDENT'
                }
            })

            console.log(result.data);
            if (result.data) {
                await query(`INSERT INTO invitations(invitationId,userId,courseId,role) VALUES('${result.data.id}','${result.data.userId}','${result.data.courseId}','${result.data.role}');`);
                return result.data
            }
        } catch (error) {
            console.log(error);
            return error.response.status;
            //res.send(error).status(400);
        }
    }

    static async enrollStudentToCourse(token, body) {
        try {
            const result = await axios({
                method: "POST",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://classroom.googleapis.com/v1/courses/${body.courseId}/students`,
                data: {
                    userId: body.studentId,
                    courseId: body.courseId,
                }
            })

            return result.data;
        } catch (error) {
            console.log(error);
            return error.response.status;
            //res.send(error).status(400);
        }
    }

    static async deletePlaylistId(playlistId, token) {
        try {
            const tasks = Object.values(JSON.parse(JSON.stringify(await query(`SELECT taskId,courseId,classRoomTaskId FROM tasks where playlistId=${playlistId};`))));
            if (tasks.length > 0) {
                const taskIds = [];
                tasks.forEach((obj) => {
                    taskIds.push(obj.taskId);
                });
                const taskIdString = taskIds.join();
                const delTask_status = `DELETE FROM tasks_status WHERE taskId IN(${taskIdString});`;
                await query(delTask_status);
                await query(`DELETE FROM student_analytics WHERE playlistId=${playlistId};`);
                await query(`DELETE FROM video WHERE playlistId = ${playlistId};`);
                await query(`DELETE FROM tasks WHERE playlistId=${playlistId};`);
                await query(`DELETE FROM playlist WHERE playlistId=${playlistId};`);

                if (token) {
                    console.log('token present');
                    tasks.forEach(async (task) => {
                        try {
                            await axios({
                                method: "DELETE",
                                headers: { Authorization: `Bearer ${token}` },
                                url: `https://classroom.googleapis.com/v1/courses/${task.courseId}/courseWork/${task.classRoomTaskId}`
                            })
                        } catch (error) {
                            console.log(error.response)
                        }

                    })
                }
                return {
                    msg: 'Playlist deleted successfully',
                    status: 200
                };
            } else {
                const playlist = Object.values(JSON.parse(JSON.stringify(await query(`SELECT * FROM playlist where playlistId=${playlistId};`))));
                if (playlist.length > 0) {
                    await query(`DELETE FROM video WHERE playlistId = ${playlistId};`);
                    await query(`DELETE FROM playlist WHERE playlistId=${playlistId};`);
                    return {
                        msg: 'Playlist deleted successfully',
                        status: 200
                    };
                }
                return {
                    msg: 'Invalid playlist id',
                    status: 400
                }
            }
        } catch (error) {
            console.log(error);
            return {
                msg: error,
                status: 500
            }
        }
    }

}
module.exports = EducatorEntity;<commit_msg>Bug: create playlist<commit_after>const dbConnection = require('../common/connection');
const util = require('util');
const query = util.promisify(dbConnection.query).bind(dbConnection);

const axios = require('axios');

class EducatorEntity {

    static async getUserInfoByToken(token) {
        try {
            const user = await axios({
                method: "get",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://www.googleapis.com/oauth2/v1/userinfo`
            })
            const userData = user.data;
            return userData;
        } catch (error) {
            console.log(error);
            //res.send('Invalid user').status(400);
        }
    }

    static async createPlaylist(body) {
        const sql = `INSERT INTO playlist (title,educatorId) VALUES ('${body.title}',${body.educatorId});`;
        console.log(sql);
        /* dbConnection.query(sql, function (err, result, fields) {
            return result;
        });*/
        const data = await query(sql);
        const lastRowId = await query(`SELECT * FROM playlist where playlistId=${data.insertId};`);
        console.log('last row id' + JSON.stringify(lastRowId));
        body.playlists.forEach(async (video) => {
            /*const insertQuery = `INSERT INTO video (videoId,playlistId,title,description,channelTitle,thumbnail,youtubeLink,duration) VALUES ('${video.videoId}',${lastRowId[0].playlistId},'${video.title}','${video.description}','${video.channelTitle}','${video.thumbnail}','${video.youtubeLink ? video.youtubeLink : null}','${video.duration}');`;
            dbConnection.query(insertQuery, function (err) {
                if (err) console.log('Insert video table:' + err)
            });*/

            var sql = "INSERT INTO video SET ?";
            // Connection attained as listed above.
            dbConnection.query(sql, {
                videoId: video.videoId, playlistId: (lastRowId[0].playlistId), title: video.title,
                description: video.description, channelTitle: video.channelTitle, thumbnail: video.thumbnail, youtubeLink: video.youtubeLink ? video.youtubeLink : null, duration: video.duration
            }, function (err) {
                // check result if err is undefined.
                if (err) {
                    console.log('Insert video error:', err);
                }
            });

        })

        return lastRowId;
    }

    static async getAllVideos(playlistId) {
        dbConnection.query(`SELECT * FROM video where playlistId=${playlistId};`, function (err, result) {
            return result;
        });
    }

    static async getAllPlaylist() {
        const data = await query('SELECT * FROM playlist;');
        const respArray = [];
        for (let i = 0; i < data.length; i++) {
            const response = {
                playlistId: data[i].playlistId,
                title: data[i].title,
                videos: Object.values(JSON.parse(JSON.stringify(await this.getPlaylist(data[i].playlistId)))),
                count: Object.values(JSON.parse(JSON.stringify(await this.getPlaylist(data[i].playlistId)))).length
            }
            respArray.push(response);
        }

        return respArray;
    }

    static async getPlaylist(playlistId) {
        const data = await query(`SELECT * FROM video where playlistId=${playlistId};`);
        return data;
    }

    static async createEducator(body) {
        const sql = `INSERT INTO educators (email,firstName,lastName) VALUES ('${body.email}','${body.firstName}','${body.lastName}');`;
        console.log(sql);
        try {
            const data = await query(sql);
            return data;
        } catch (err) {
            if (err.code === 'ER_DUP_ENTRY') {
                return await query(`SELECT * FROM educators where email='${body.email}';`);
            }
            return err;
        }

    }

    static async assignTask(token, body) {
        try {
            const video = Object.values(JSON.parse(JSON.stringify(await query(`SELECT * FROM video where playlistId=${body.playlistId} LIMIT 1;`))));
            const result = await axios({
                method: "POST",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://classroom.googleapis.com/v1/courses/${body.courseId}/courseWork`,
                data: {
                    assigneeMode: "ALL_STUDENTS",
                    courseId: body.courseId,
                    title: body.taskName,
                    maxPoints: 100,
                    workType: "ASSIGNMENT",
                    state: "PUBLISHED",
                    materials: [
                        {
                            link: {
                                url: `${process.env.STD_PORTAL}?courseId=${body.courseId}&videoId=${video[0].videoId}`
                            }
                        }
                    ]
                }
            })

            console.log(result.data);
            body.classRoomTaskId = result.data.id;
        } catch (error) {
            console.log(error);
            return error.response.status;
            //res.send(error).status(400);
        }

        const sql = `INSERT INTO tasks(taskName,playlistId,courseId,studentId,classRoomTaskId) VALUES ('${body.taskName}',${body.playlistId},'${body.courseId}',${body.studentId ? body.studentId : null},'${body.classRoomTaskId}');`;
        console.log(sql);
        const data = await query(sql);

        const lastRowId = await query(`SELECT * FROM tasks where taskId=${data.insertId};`);
        body.taskId = lastRowId[0].taskId;
        const playlistId = body.playlistId;

        if (body.studentId && (body.courseId === null || body.courseId === undefined)) {
            body.status = 'NotStarted';
            await this.taskStatus(body);
        }
        if (body.courseId && (body.studentId === null || body.studentId === undefined)) {
            const students = await query(`SELECT * FROM students;`);
            dbConnection.query(
                'INSERT INTO tasks_status(taskId,studentId,status,courseId,classRoomTaskId) VALUES ?',
                [students.map(item => [body.taskId, item.studentId, 'NotStarted', body.courseId, body.classRoomTaskId])],
                (error) => {
                    console.log(error)
                }
            );

            const videos = Object.values(JSON.parse(JSON.stringify(await this.getPlaylist(playlistId))));
            for (let i = 0; i < videos.length; i++) {
                dbConnection.query(
                    'INSERT INTO student_analytics(videoId,studentId,videoStatus,videoProgress,playlistId,courseId,classRoomTaskId) VALUES ?',
                    [students.map(item => [videos[i].id, item.studentId, 'NotStarted', '00', playlistId, body.courseId, body.classRoomTaskId])],
                    (error) => {
                        console.log(error)
                    }
                );
            }
        }
        return data;
    }

    static async taskStatus(body) {
        if (body.status === 'NotStarted' || body.status === 'Inprogress' || body.status === 'Completed') {
            const sql = `INSERT INTO tasks_status(taskId,studentId,status) VALUES (${body.taskId},${body.studentId},'${body.status}');`;
            console.log(sql);
            const data = await query(sql);
            return data;
        } else {
            return {
                status: 400,
                reason: "Invalid task status"
            }
        }

    }

    static async updateTaskStatus(taskId, studentId, status) {
        if (status === 'NotStarted' || status === 'Inprogress' || status === 'Completed') {
            const sql = `UPDATE tasks_status SET status = '${status}' WHERE taskId = ${taskId} AND studentId = ${studentId};`;
            console.log(sql);
            const data = await query(sql);
            console.log(data);
            return data;
        } else {
            return {
                status: 400,
                reason: "Invalid task status"
            }
        }

    }

    static async addVideosToPlaylist(playlistId, body) {
        body.playlists.forEach((video) => {
            const insertQuery = `INSERT INTO video (videoId,playlistId,title,description,channelTitle,thumbnail,youtubeLink,duration) VALUES ('${video.videoId}',${playlistId},'${video.title}','${video.description}','${video.channelTitle}','${video.thumbnail}','${video.youtubeLink ? video.youtubeLink : null}','${video.duration}');`;
            dbConnection.query(insertQuery, function (err) {
                if (err) console.log('Insert video table:' + err)
            });
        })
        return await this.getPlaylist(playlistId);
    }

    static async getEducatorByEmail(email) {
        const sql = `SELECT * FROM educators where email = '${email}'`;
        console.log('query:', sql);
        const data = await query(sql);
        return data;
    }

    static async pullCourseDataFromClassRoomApi(token) {
        let courses;
        let userData;
        try {
            const result = await axios({
                method: "get",
                headers: { Authorization: `Bearer ${token}` },
                url: 'https://classroom.googleapis.com/v1/courses?courseStates=ACTIVE'
            })
            courses = result.data.courses;
        } catch (error) {
            console.log(error);
            return error.response.status;
            //res.send(error).status(400);
        }

        try {
            const user = await axios({
                method: "get",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://www.googleapis.com/oauth2/v1/userinfo`
            })
            userData = user.data;
        } catch (error) {
            console.log(error);
            //res.send('Invalid user').status(400);
        }

        await query(`DELETE FROM courses WHERE creator='${userData.email}';`);

        await query('INSERT INTO courses(courseId,name,descriptionHeading,ownerId,creator,courseState,creationTime) VALUES ?',
            [courses.map(item => [item.id, item.name, item.descriptionHeading, item.ownerId, userData.email, item.courseState, new Date(item.creationTime).toJSON().slice(0, 19).replace('T', ' ')])]);

        const result = await query(`SELECT * FROM courses WHERE creator='${userData.email}';`);
        return result;
    }

    static async invitation(token, body) {
        try {
            const result = await axios({
                method: "POST",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://classroom.googleapis.com/v1/invitations`,
                data: {
                    userId: body.studentId,
                    courseId: body.courseId,
                    role: 'STUDENT'
                }
            })

            console.log(result.data);
            if (result.data) {
                await query(`INSERT INTO invitations(invitationId,userId,courseId,role) VALUES('${result.data.id}','${result.data.userId}','${result.data.courseId}','${result.data.role}');`);
                return result.data
            }
        } catch (error) {
            console.log(error);
            return error.response.status;
            //res.send(error).status(400);
        }
    }

    static async enrollStudentToCourse(token, body) {
        try {
            const result = await axios({
                method: "POST",
                headers: { Authorization: `Bearer ${token}` },
                url: `https://classroom.googleapis.com/v1/courses/${body.courseId}/students`,
                data: {
                    userId: body.studentId,
                    courseId: body.courseId,
                }
            })

            return result.data;
        } catch (error) {
            console.log(error);
            return error.response.status;
            //res.send(error).status(400);
        }
    }

    static async deletePlaylistId(playlistId, token) {
        try {
            const tasks = Object.values(JSON.parse(JSON.stringify(await query(`SELECT taskId,courseId,classRoomTaskId FROM tasks where playlistId=${playlistId};`))));
            if (tasks.length > 0) {
                const taskIds = [];
                tasks.forEach((obj) => {
                    taskIds.push(obj.taskId);
                });
                const taskIdString = taskIds.join();
                const delTask_status = `DELETE FROM tasks_status WHERE taskId IN(${taskIdString});`;
                await query(delTask_status);
                await query(`DELETE FROM student_analytics WHERE playlistId=${playlistId};`);
                await query(`DELETE FROM video WHERE playlistId = ${playlistId};`);
                await query(`DELETE FROM tasks WHERE playlistId=${playlistId};`);
                await query(`DELETE FROM playlist WHERE playlistId=${playlistId};`);

                if (token) {
                    console.log('token present');
                    tasks.forEach(async (task) => {
                        try {
                            await axios({
                                method: "DELETE",
                                headers: { Authorization: `Bearer ${token}` },
                                url: `https://classroom.googleapis.com/v1/courses/${task.courseId}/courseWork/${task.classRoomTaskId}`
                            })
                        } catch (error) {
                            console.log(error.response)
                        }

                    })
                }
                return {
                    msg: 'Playlist deleted successfully',
                    status: 200
                };
            } else {
                const playlist = Object.values(JSON.parse(JSON.stringify(await query(`SELECT * FROM playlist where playlistId=${playlistId};`))));
                if (playlist.length > 0) {
                    await query(`DELETE FROM video WHERE playlistId = ${playlistId};`);
                    await query(`DELETE FROM playlist WHERE playlistId=${playlistId};`);
                    return {
                        msg: 'Playlist deleted successfully',
                        status: 200
                    };
                }
                return {
                    msg: 'Invalid playlist id',
                    status: 400
                }
            }
        } catch (error) {
            console.log(error);
            return {
                msg: error,
                status: 500
            }
        }
    }

}
module.exports = EducatorEntity;<|endoftext|>


<commit_before>/**
 * This file contains all necessary Angular service definitions for 'frontend.core.layout' module.
 *
 * Note that this file should only contain services and nothing else.
 */
(function() {
  'use strict';

  // Generic service to return all available menu items for main level navigation.
  angular.module('frontend.core.layout')
    .factory('HeaderNavigationItems', [
      'AccessLevels',
      function factory(AccessLevels) {
        return [
          {
            state: 'examples.about',
            title: 'About',
            access: AccessLevels.anon
          },
          {
            state: 'examples',
            title: 'Books Visualization',
            access: AccessLevels.anon
          },
          {
            state: 'admin',
            title: 'Admin',
            access: AccessLevels.admin
          }
        ];
      }
    ])
  ;

  // Generic service to return all available menu items for specified sub level navigation.
  angular.module('frontend.core.layout')
    .factory('ContentNavigationItems', [
      'AccessLevels',
      function factory(AccessLevels) {
        var items = {
          'examples': [
           /* {
              state: 'examples.books',
              title: 'Books',
              access: AccessLevels.user
            },*/
            {
              state: 'examples.genderviz',
              title: 'Visualization',
              access: AccessLevels.anon
            }
          ],
          'admin': [
            {
              state: '',
              title: 'Users',
              access: AccessLevels.admin
            },
            {
              state: '',
              title: 'Request log',
              access: AccessLevels.admin
            },
            {
              state: 'admin.login-history',
              title: 'Login history',
              access: AccessLevels.admin
            }
          ]
        };

        return {
          getItems: function getItems(section) {
            return items[section];
          }
        };
      }
    ])
  ;

  /**
   * Service which contains information about all used files (back- and frontend) within specified example page.
   * These files are shown in example page info modal, so that users can easily see what current example page is
   * using to do things.
   */
  angular.module('frontend.core.layout')
    .factory('NavigationInfoModalFiles', [
      '_',
      function factory(_) {
        /**
         * Base url for code repository.
         *
         * @type {string}
         */
        var repository = 'https://github.com/nikolausn/lab-keywords-gender-viz';

        /**
         * Type configuration for files.
         *
         * @type    {{
         *            generic: {
         *              controller: string,
         *              data: string,
         *              model: string,
         *              template: string
         *            },
         *            backend: {
         *              baseController: string,
         *              baseModel: string
         *            },
         *            frontend: {
         *              module: string,
         *              listConfig: string
         *            }
         *          }}
         */
        var types = {
          generic: {
            controller: 'Used controller.',
            data: 'Initial data that is loaded to database at first time that sails lift.',
            model: 'Used model.',
            template: 'Used HTML template.'
          },
          backend: {
            baseController: 'Generic base controller that is extended by real controllers.',
            baseModel: 'Generic base model that is extended by real models.',
            policy: {
              authenticated: 'Authentication policy that will check if request contains correct JWT or not.',
              passport: 'Policy to initialize passport.js library to use.'
            }
          },
          frontend: {
            module: 'Current angular module configuration.',
            modelFactory: 'Generic model factory that all individual models uses. This contains default functions for each model.',
            dataService: 'Generic data service, which handles all the communications between back- and frontend via $sailsSocket service.',
            listConfig: 'Service that contains all list specified configurations (title items, default configurations, etc.).',
            backendConfig: 'Backend config, this contains backend url and other "static" backend specified definitions.',
            authInterceptor: 'Authentication interceptor, that attach JWT to $http and $sailsSockets requests.',
            errorInterceptor: 'Generic error interceptor, this will handle all error situations and shows those to user.',
            directive: 'Used directive(s) in this example page.'
          }
        };

        /**
         * Generic files that are used across each GUI example.
         *
         * @type    {{}}
         */
        var generic = {
          'backend': {
            'Backend generic': [
              {
                url: repository + 'backend/api/base/controller.js',
                title: 'controller.js',
                info: types.backend.baseController
              },
              {
                url: repository + 'backend/api/base/model.js',
                title: 'model.js',
                info: types.backend.baseModel
              },
              {
                url: repository + 'backend/api/policies/Authenticated.js',
                title: 'Authenticated.js',
                info: types.backend.policy.authenticated
              },
              {
                url: repository + 'backend/api/policies/Passport.js',
                title: 'Passport.js',
                info: types.backend.policy.passport
              }
            ]
          },
          'frontend': {
            'Frontend generic': [
              {
                url: repository + 'frontend/src/app/core/services/ListConfigService.js',
                title: 'ListConfigService.js',
                info: types.frontend.listConfig
              },
              {
                url: repository + 'frontend/src/app/core/models/factory.js',
                title: 'factory.js',
                info: types.frontend.modelFactory
              },
              {
                url: repository + 'frontend/src/app/core/services/DataService.js',
                title: 'DataService.js',
                info: types.frontend.dataService
              },
              {
                url: repository + 'frontend/src/app/core/constants/BackendConfig.js',
                title: 'BackendConfig.js',
                info: types.frontend.backendConfig
              },
              {
                url: repository + 'frontend/src/app/core/interceptors/AuthInterceptor.js',
                title: 'AuthInterceptor.js',
                info: types.frontend.authInterceptor
              },
              {
                url: repository + 'frontend/src/app/core/interceptors/ErrorInterceptor.js',
                title: 'ErrorInterceptor.js',
                info: types.frontend.errorInterceptor
              }
            ]
          }
        };

        /**
         * Actual data for each example page. This data contains used files in each example GUI item, these
         * files are grouped to following sections:
         *  - backend
         *  - backend (generic)
         *  - frontend
         *  - frontend (generic)
         *
         * @type    {{}}
         */
        var data = {
          'examples.books': {
            'Backend': [
              {
                url: repository + 'backend/api/models/Book.js',
                title: 'Book.js',
                info: types.generic.model
              },
              {
                url: repository + 'backend/api/controllers/BookController.js',
                title: 'BookController.js',
                info: types.generic.controller
              },
              {
                url: repository + 'backend/test/fixtures/Book.json',
                title: 'Book.json',
                info: types.generic.data
              }
            ],
            'Frontend': [
              {
                url: repository + 'frontend/src/app/examples/book/book.js',
                title: 'book.js',
                info: types.frontend.module
              },
              {
                url: repository + 'frontend/src/app/examples/book/book-controllers.js',
                title: 'book-controllers.js',
                info: types.generic.controller
              },
              {
                url: repository + 'frontend/src/app/examples/book/book-models.js',
                title: 'book-models.js',
                info: types.generic.model
              },
              {
                url: repository + 'frontend/src/app/examples/book/list.html',
                title: 'list.html',
                info: types.generic.template
              }
            ]
          },
          'examples.authors': {
            'Backend': [
              {
                url: repository + 'backend/api/models/Author.js',
                title: 'Author.js',
                info: types.generic.model
              },
              {
                url: repository + 'backend/api/controllers/AuthorController.js',
                title: 'AuthorController.js',
                info: types.generic.controller
              },
              {
                url: repository + 'backend/test/fixtures/Author.json',
                title: 'Author.json',
                info: types.generic.data
              }
            ],
            'Frontend': [
              {
                url: repository + 'frontend/src/app/examples/author/author.js',
                title: 'author.js',
                info: types.frontend.module
              },
              {
                url: repository + 'frontend/src/app/examples/author/author-controllers.js',
                title: 'author-controllers.js',
                info: types.generic.controller
              },
              {
                url: repository + 'frontend/src/app/examples/author/author-models.js',
                title: 'author-models.js',
                info: types.generic.model
              },
              {
                url: repository + 'frontend/src/app/examples/author/list.html',
                title: 'list.html',
                info: types.generic.template
              }
            ]
          },
          'examples.messages': {
            'Frontend': [
              {
                url: repository + 'frontend/src/app/examples/messages/messages.js',
                title: 'messages.js',
                info: types.frontend.module
              },
              {
                url: repository + 'frontend/src/app/examples/messages/messages-controllers.js',
                title: 'messages-controllers.js',
                info: types.generic.controller
              },
              {
                url: repository + 'frontend/src/app/examples/messages/messages.html',
                title: 'messages.html',
                info: types.generic.template
              }
            ],
            'Frontend generic': [
              {
                url: repository + 'frontend/src/app/core/interceptors/ErrorInterceptor.js',
                title: 'ErrorInterceptor.js',
                info: types.frontend.errorInterceptor
              },
              {
                url: repository + 'frontend/src/app/core/services/MessageService.js',
                title: 'MessageService.js',
                info: 'Service to show messages to users via toastr service.'
              },
              {
                url: repository + 'frontend/src/app/core/services/HttpStatusService.js',
                title: 'HttpStatusService.js',
                info: 'Generic HTTP status service that contains helper methods for HTTP status code handling.'
              }
            ]
          },
          'examples.chat': {
            'Backend': [
              {
                url: repository + 'backend/api/models/Message.js',
                title: 'Message.js',
                info: types.generic.model
              },
              {
                url: repository + 'backend/api/controllers/MessageController.js',
                title: 'MessageController.js',
                info: types.generic.controller
              }
            ],
            'Frontend': [
              {
                url: repository + 'frontend/src/app/examples/chat/chat.js',
                title: 'chat.js',
                info: types.frontend.module
              },
              {
                url: repository + 'frontend/src/app/examples/chat/chat-controllers.js',
                title: 'chat-controllers.js',
                info: types.generic.controller
              },
              {
                url: repository + 'frontend/src/app/examples/chat/chat-directives.js',
                title: 'chat-directives.js',
                info: types.frontend.directive
              },
              {
                url: repository + 'frontend/src/app/examples/chat/chat-models.js',
                title: 'chat-models.js',
                info: types.generic.model
              },
              {
                url: repository + 'frontend/src/app/examples/chat/chat.html',
                title: 'chat.html',
                info: types.generic.template
              }
            ]
          }
        };

        return {
          /**
           * Service function to fetch all defined backend and frontend used files.
           *
           * @returns {{}}    All the file definitions
           */
          getAll: function getAll() {
            return data;
          },
          /**
           * Service function to fetch specified GUI used backend and frontend used files.
           *
           * @param   {string}    state
           *
           * @returns {{}}
           */
          get: function get(state) {
            var files = data[state];

            switch (state) {
              case 'examples.books':
              case 'examples.authors':
              case 'examples.chat':
                files = _.merge(files, generic.backend, generic.frontend);
                break;
              default:
                break;
            }

            return files;
          }
        };
      }
    ])
  ;
}());
<commit_msg>change ui<commit_after>/**
 * This file contains all necessary Angular service definitions for 'frontend.core.layout' module.
 *
 * Note that this file should only contain services and nothing else.
 */
(function() {
  'use strict';

  // Generic service to return all available menu items for main level navigation.
  angular.module('frontend.core.layout')
    .factory('HeaderNavigationItems', [
      'AccessLevels',
      function factory(AccessLevels) {
        return [
          {
            state: 'examples.about',
            title: 'About',
            access: AccessLevels.anon
          },
          {
            state: 'examples',
            title: 'Visualization',
            access: AccessLevels.anon
          },
          {
            state: 'admin',
            title: 'Admin',
            access: AccessLevels.admin
          }
        ];
      }
    ])
  ;

  // Generic service to return all available menu items for specified sub level navigation.
  angular.module('frontend.core.layout')
    .factory('ContentNavigationItems', [
      'AccessLevels',
      function factory(AccessLevels) {
        var items = {
          'examples': [
           /* {
              state: 'examples.books',
              title: 'Books',
              access: AccessLevels.user
            },*/
            {
              state: 'examples.genderviz',
              title: 'Display Visualization',
              access: AccessLevels.anon
            }
          ],
          'admin': [
            {
              state: '',
              title: 'Users',
              access: AccessLevels.admin
            },
            {
              state: '',
              title: 'Request log',
              access: AccessLevels.admin
            },
            {
              state: 'admin.login-history',
              title: 'Login history',
              access: AccessLevels.admin
            }
          ]
        };

        return {
          getItems: function getItems(section) {
            return items[section];
          }
        };
      }
    ])
  ;

  /**
   * Service which contains information about all used files (back- and frontend) within specified example page.
   * These files are shown in example page info modal, so that users can easily see what current example page is
   * using to do things.
   */
  angular.module('frontend.core.layout')
    .factory('NavigationInfoModalFiles', [
      '_',
      function factory(_) {
        /**
         * Base url for code repository.
         *
         * @type {string}
         */
        var repository = 'https://github.com/nikolausn/lab-keywords-gender-viz';

        /**
         * Type configuration for files.
         *
         * @type    {{
         *            generic: {
         *              controller: string,
         *              data: string,
         *              model: string,
         *              template: string
         *            },
         *            backend: {
         *              baseController: string,
         *              baseModel: string
         *            },
         *            frontend: {
         *              module: string,
         *              listConfig: string
         *            }
         *          }}
         */
        var types = {
          generic: {
            controller: 'Used controller.',
            data: 'Initial data that is loaded to database at first time that sails lift.',
            model: 'Used model.',
            template: 'Used HTML template.'
          },
          backend: {
            baseController: 'Generic base controller that is extended by real controllers.',
            baseModel: 'Generic base model that is extended by real models.',
            policy: {
              authenticated: 'Authentication policy that will check if request contains correct JWT or not.',
              passport: 'Policy to initialize passport.js library to use.'
            }
          },
          frontend: {
            module: 'Current angular module configuration.',
            modelFactory: 'Generic model factory that all individual models uses. This contains default functions for each model.',
            dataService: 'Generic data service, which handles all the communications between back- and frontend via $sailsSocket service.',
            listConfig: 'Service that contains all list specified configurations (title items, default configurations, etc.).',
            backendConfig: 'Backend config, this contains backend url and other "static" backend specified definitions.',
            authInterceptor: 'Authentication interceptor, that attach JWT to $http and $sailsSockets requests.',
            errorInterceptor: 'Generic error interceptor, this will handle all error situations and shows those to user.',
            directive: 'Used directive(s) in this example page.'
          }
        };

        /**
         * Generic files that are used across each GUI example.
         *
         * @type    {{}}
         */
        var generic = {
          'backend': {
            'Backend generic': [
              {
                url: repository + 'backend/api/base/controller.js',
                title: 'controller.js',
                info: types.backend.baseController
              },
              {
                url: repository + 'backend/api/base/model.js',
                title: 'model.js',
                info: types.backend.baseModel
              },
              {
                url: repository + 'backend/api/policies/Authenticated.js',
                title: 'Authenticated.js',
                info: types.backend.policy.authenticated
              },
              {
                url: repository + 'backend/api/policies/Passport.js',
                title: 'Passport.js',
                info: types.backend.policy.passport
              }
            ]
          },
          'frontend': {
            'Frontend generic': [
              {
                url: repository + 'frontend/src/app/core/services/ListConfigService.js',
                title: 'ListConfigService.js',
                info: types.frontend.listConfig
              },
              {
                url: repository + 'frontend/src/app/core/models/factory.js',
                title: 'factory.js',
                info: types.frontend.modelFactory
              },
              {
                url: repository + 'frontend/src/app/core/services/DataService.js',
                title: 'DataService.js',
                info: types.frontend.dataService
              },
              {
                url: repository + 'frontend/src/app/core/constants/BackendConfig.js',
                title: 'BackendConfig.js',
                info: types.frontend.backendConfig
              },
              {
                url: repository + 'frontend/src/app/core/interceptors/AuthInterceptor.js',
                title: 'AuthInterceptor.js',
                info: types.frontend.authInterceptor
              },
              {
                url: repository + 'frontend/src/app/core/interceptors/ErrorInterceptor.js',
                title: 'ErrorInterceptor.js',
                info: types.frontend.errorInterceptor
              }
            ]
          }
        };

        /**
         * Actual data for each example page. This data contains used files in each example GUI item, these
         * files are grouped to following sections:
         *  - backend
         *  - backend (generic)
         *  - frontend
         *  - frontend (generic)
         *
         * @type    {{}}
         */
        var data = {
          'examples.books': {
            'Backend': [
              {
                url: repository + 'backend/api/models/Book.js',
                title: 'Book.js',
                info: types.generic.model
              },
              {
                url: repository + 'backend/api/controllers/BookController.js',
                title: 'BookController.js',
                info: types.generic.controller
              },
              {
                url: repository + 'backend/test/fixtures/Book.json',
                title: 'Book.json',
                info: types.generic.data
              }
            ],
            'Frontend': [
              {
                url: repository + 'frontend/src/app/examples/book/book.js',
                title: 'book.js',
                info: types.frontend.module
              },
              {
                url: repository + 'frontend/src/app/examples/book/book-controllers.js',
                title: 'book-controllers.js',
                info: types.generic.controller
              },
              {
                url: repository + 'frontend/src/app/examples/book/book-models.js',
                title: 'book-models.js',
                info: types.generic.model
              },
              {
                url: repository + 'frontend/src/app/examples/book/list.html',
                title: 'list.html',
                info: types.generic.template
              }
            ]
          },
          'examples.authors': {
            'Backend': [
              {
                url: repository + 'backend/api/models/Author.js',
                title: 'Author.js',
                info: types.generic.model
              },
              {
                url: repository + 'backend/api/controllers/AuthorController.js',
                title: 'AuthorController.js',
                info: types.generic.controller
              },
              {
                url: repository + 'backend/test/fixtures/Author.json',
                title: 'Author.json',
                info: types.generic.data
              }
            ],
            'Frontend': [
              {
                url: repository + 'frontend/src/app/examples/author/author.js',
                title: 'author.js',
                info: types.frontend.module
              },
              {
                url: repository + 'frontend/src/app/examples/author/author-controllers.js',
                title: 'author-controllers.js',
                info: types.generic.controller
              },
              {
                url: repository + 'frontend/src/app/examples/author/author-models.js',
                title: 'author-models.js',
                info: types.generic.model
              },
              {
                url: repository + 'frontend/src/app/examples/author/list.html',
                title: 'list.html',
                info: types.generic.template
              }
            ]
          },
          'examples.messages': {
            'Frontend': [
              {
                url: repository + 'frontend/src/app/examples/messages/messages.js',
                title: 'messages.js',
                info: types.frontend.module
              },
              {
                url: repository + 'frontend/src/app/examples/messages/messages-controllers.js',
                title: 'messages-controllers.js',
                info: types.generic.controller
              },
              {
                url: repository + 'frontend/src/app/examples/messages/messages.html',
                title: 'messages.html',
                info: types.generic.template
              }
            ],
            'Frontend generic': [
              {
                url: repository + 'frontend/src/app/core/interceptors/ErrorInterceptor.js',
                title: 'ErrorInterceptor.js',
                info: types.frontend.errorInterceptor
              },
              {
                url: repository + 'frontend/src/app/core/services/MessageService.js',
                title: 'MessageService.js',
                info: 'Service to show messages to users via toastr service.'
              },
              {
                url: repository + 'frontend/src/app/core/services/HttpStatusService.js',
                title: 'HttpStatusService.js',
                info: 'Generic HTTP status service that contains helper methods for HTTP status code handling.'
              }
            ]
          },
          'examples.chat': {
            'Backend': [
              {
                url: repository + 'backend/api/models/Message.js',
                title: 'Message.js',
                info: types.generic.model
              },
              {
                url: repository + 'backend/api/controllers/MessageController.js',
                title: 'MessageController.js',
                info: types.generic.controller
              }
            ],
            'Frontend': [
              {
                url: repository + 'frontend/src/app/examples/chat/chat.js',
                title: 'chat.js',
                info: types.frontend.module
              },
              {
                url: repository + 'frontend/src/app/examples/chat/chat-controllers.js',
                title: 'chat-controllers.js',
                info: types.generic.controller
              },
              {
                url: repository + 'frontend/src/app/examples/chat/chat-directives.js',
                title: 'chat-directives.js',
                info: types.frontend.directive
              },
              {
                url: repository + 'frontend/src/app/examples/chat/chat-models.js',
                title: 'chat-models.js',
                info: types.generic.model
              },
              {
                url: repository + 'frontend/src/app/examples/chat/chat.html',
                title: 'chat.html',
                info: types.generic.template
              }
            ]
          }
        };

        return {
          /**
           * Service function to fetch all defined backend and frontend used files.
           *
           * @returns {{}}    All the file definitions
           */
          getAll: function getAll() {
            return data;
          },
          /**
           * Service function to fetch specified GUI used backend and frontend used files.
           *
           * @param   {string}    state
           *
           * @returns {{}}
           */
          get: function get(state) {
            var files = data[state];

            switch (state) {
              case 'examples.books':
              case 'examples.authors':
              case 'examples.chat':
                files = _.merge(files, generic.backend, generic.frontend);
                break;
              default:
                break;
            }

            return files;
          }
        };
      }
    ])
  ;
}());
<|endoftext|>


<commit_before>/*
	WebPlotDigitizer - http://arohatgi.info/WebPlotDigitizer

	Copyright 2010-2013 Ankit Rohatgi <ankitrohatgi@hotmail.com>

	This file is part of WebPlotDigitizer.

    WebPlotDigitizer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    WebPlotDigitizer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with WebPlotDigitizer.  If not, see <http://www.gnu.org/licenses/>.

*/

/* Parse dates and convert back and forth to Julian days */

var dateConverter = {

	parse: function(input) {
				if(input == null) {
					return null;
				}

				if(input.indexOf("/") === -1) {
					return null;
				}

				return this.toJD(input);
			},

	// Convert to Julian Date
	toJD: function(dateString) {
				return 0;
			},

	// Convert back from Julian Date
	fromJD: function(jd) {
				return {
					year: 0,
					month: 0,
					day: 0
				};
			},

	formatDate: function(dateObject, formatString) {
				return dateObject.year + "/" + dateObject.month + "/" + dateObject.date;
			}
};
<commit_msg>Partial implementation of date conversion object. Input parsing has been added, output formatting needs work<commit_after>/*
	WebPlotDigitizer - http://arohatgi.info/WebPlotDigitizer

	Copyright 2010-2013 Ankit Rohatgi <ankitrohatgi@hotmail.com>

	This file is part of WebPlotDigitizer.

    WebPlotDigitizer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    WebPlotDigitizer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with WebPlotDigitizer.  If not, see <http://www.gnu.org/licenses/>.

*/

/* Parse dates and convert back and forth to Julian days */

var dateConverter = {

	parse: function(input) {
				if(input == null) {
					return null;
				}

				if(input.indexOf("/") === -1) {
					return null;
				}

				return this.toJD(input);
			},

	// Convert to Julian Date
	toJD: function(dateString) {
				var dateParts = dateString.split("/"),
					year,
					month,
					day,
					tempDate,
					rtnValue;

				if(dateParts.length <= 0 || dateParts.length > 3) {
					return null;
				}

				year = parseInt(dateParts[0], 10);

				month = parseInt(dateParts[1] === undefined ? 0 : dateParts[1], 10);

				day = parseInt(dateParts[2] === undefined ? 1 : dateParts[2], 10);

				if(isNaN(year) || isNaN(month) || isNaN(day)) {
					return null;
				}

				if(month > 12 || month < 1) {
					return null;
				}

				if(day > 31 || day < 1) {
					return null;
				}

				// Temporary till I figure out julian dates:
				tempDate = new Date();
				tempDate.setUTCFullYear(year);
				tempDate.setUTCMonth(month-1);
				tempDate.setUTCDate(day);
				rtnValue = parseFloat(Date.parse(tempDate));
				if(!isNaN(rtnValue)) {
					return rtnValue;
				}
				return null;
			},

	// Convert back from Julian Date
	fromJD: function(jd) {

				// Temporary till I figure out julian dates:
				var msInDay = 24*60*60*1000,
					roundedDate = Math.round(jd/msInDay)*msInDay,
					tempDate = new Date(Date.parse(jd));

				return {
					year: tempDate.getUTCFullYear(),
					month: tempDate.getUTCMonth(),
					day: tempDate.getUTCDate()
				};
			},

	formatDate: function(dateObject, formatString) {
				var longMonths = [
									"January",
									"February",
									"March",
									"April",
									"May",
									"June",
									"July",
									"August",
									"September",
									"October",
									"November",
									"December"
								],
					shortMonths = [
									"Jan",
									"Feb",
									"Mar",
									"Apr",
									"May",
									"Jun",
									"Jul",
									"Aug",
									"Sep",
									"Oct",
									"Nov",
									"Dec"
								];

				return dateObject.year + "/" + dateObject.month + "/" + dateObject.date;
			},

	getFormatString: function(dateString) {
				var dateParts = dateString.split("/"),
					year,
					month,
					day,
					formatString = 'yyyy/mm/dd';

				if(dateParts.length >= 1) {
					formatString = 'yyyy';
				}

				if(dateParts.length >= 2) {
					formatString += '/mm';
				}

				if(dateParts.length === 3) {
					formatString += '/dd';
				}

				return formatString;
			}
};
<|endoftext|>


<commit_before>const path = require('path'),
    config = require('../config');

exports.assetsPath = _path => {
    return path.posix.join(config.assetsDirectory, _path);
};

exports.assetsSubPath = _path => {
    return path.posix.join(config.assetsSubDirectory, _path);
};

exports.assetsVendorsAbsolutePath = _path => {
    return path.posix.join(config.build.assetsRoot, exports.assetsSubPath(`vendors/${_path}`));
};<commit_msg>update build<commit_after>const path = require('path'),

    config = require('./config.js');

exports.assetsPath = _path => {
    return path.posix.join(config.assetsDirectory, _path);
};

exports.assetsSubPath = _path => {
    return path.posix.join(config.assetsSubDirectory, _path);
};

exports.assetsVendorsAbsolutePath = _path => {
    return path.posix.join(config.build.assetsRoot, exports.assetsSubPath(`vendors/${_path}`));
};<|endoftext|>