<commit_before>import moment from 'moment';
import DAO from '../../../../data/dao';
import { cloneObject, getPropertyValue } from '../../../../../_common/utility';
import { localize } from '../../../../../_common/localize';
import { get as getLanguage } from '../../../../../_common/language';
import { buildDurationConfig } from './duration';

const ContractType = (() => {
    /**
     * components can be undef or an array containing any of: 'start_date', 'barrier', 'last_digit'
     *     ['duration', 'amount'] are omitted, as they're available in all contract types
     */
    const contract_types = {
        rise_fall  : { title: localize('Rise/Fall'),                  trade_types: ['CALL', 'PUT'],               components: ['start_date'], barrier_count: 0 },
        high_low   : { title: localize('Higher/Lower'),               trade_types: ['CALL', 'PUT'],               components: ['barrier'],    barrier_count: 1 },
        touch      : { title: localize('Touch/No Touch'),             trade_types: ['ONETOUCH', 'NOTOUCH'],       components: ['barrier'] },
        end        : { title: localize('Ends Between/Ends Outside'),  trade_types: ['EXPIRYMISS', 'EXPIRYRANGE'], components: ['barrier'] },
        stay       : { title: localize('Stays Between/Goes Outside'), trade_types: ['RANGE', 'UPORDOWN'],         components: ['barrier'] },
        asian      : { title: localize('Asians'),                     trade_types: ['ASIANU', 'ASIAND'],          components: [] },
        match_diff : { title: localize('Matches/Differs'),            trade_types: ['DIGITMATCH', 'DIGITDIFF'],   components: ['last_digit'] },
        even_odd   : { title: localize('Even/Odd'),                   trade_types: ['DIGITODD', 'DIGITEVEN'],     components: [] },
        over_under : { title: localize('Over/Under'),                 trade_types: ['DIGITOVER', 'DIGITUNDER'],   components: ['last_digit'] },
        lb_call    : { title: localize('High-Close'),                 trade_types: ['LBFLOATCALL'],               components: [] },
        lb_put     : { title: localize('Close-Low'),                  trade_types: ['LBFLOATPUT'],                components: [] },
        lb_high_low: { title: localize('High-Low'),                   trade_types: ['LBHIGHLOW'],                 components: [] },
    };

    const contract_categories = {
        [localize('Up/Down')]       : ['rise_fall', 'high_low'],
        [localize('Touch/No Touch')]: ['touch'],
        [localize('In/Out')]        : ['end', 'stay'],
        [localize('Asians')]        : ['asian'],
        [localize('Digits')]        : ['match_diff', 'even_odd', 'over_under'],
        [localize('Lookback')]      : ['lb_call', 'lb_put', 'lb_high_low'],
    };

    let available_contract_types = {};
    let available_categories     = {};

    const buildContractTypesConfig = (symbol) => DAO.getContractsFor(symbol).then(r => {
        available_contract_types = {};
        available_categories = cloneObject(contract_categories); // To preserve the order (will clean the extra items later in this function)
        r.contracts_for.available.forEach((contract) => {
            const type = Object.keys(contract_types).find(key => (
                contract_types[key].trade_types.indexOf(contract.contract_type) !== -1 &&
                (typeof contract_types[key].barrier_count === 'undefined' || +contract_types[key].barrier_count === contract.barriers) // To distinguish betweeen Rise/Fall & Higher/Lower
            ));

            if (!Exceptions.isExcluded(type)) {
                if (!available_contract_types[type]) {
                    // extend contract_categories to include what is needed to create the contract list
                    const sub_cats = available_categories[Object.keys(available_categories)
                        .find(key => available_categories[key].indexOf(type) !== -1)];
                    sub_cats[sub_cats.indexOf(type)] = { value: type, text: localize(contract_types[type].title) };

                    // populate available contract types
                    available_contract_types[type]        = cloneObject(contract_types[type]);
                    available_contract_types[type].config = {};
                }

                /*
                add to this config if a value you are looking for does not exist yet
                accordingly create a function to retrieve the value
                config: {
                    has_spot: 1,
                    durations: {
                        min_max: {
                            spot: {
                                tick: {
                                    min: 5, // value in ticks, as cannot convert to seconds
                                    max: 10,
                                },
                                intraday: {
                                    min: 18000, // all values converted to seconds
                                    max: 86400,
                                },
                                daily: {
                                    min: 86400,
                                    max: 432000,
                                },
                            },
                            forward: {
                                intraday: {
                                    min: 18000,
                                    max: 86400,
                                },
                            },
                        },
                        units_display: {
                            spot: [
                                { text: 'ticks', value: 't' },
                                { text: 'seconds', value: 's' },
                                { text: 'minutes', value: 'm' },
                                { text: 'hours', value: 'h' },
                                { text: 'days', value: 'd' },
                            ],
                            forward: [
                                { text: 'days', value: 'd' },
                            ],
                        },
                    },
                    forward_starting_dates: [
                        { text: 'Mon - 19 Mar, 2018', open: 1517356800, close: 1517443199 },
                        { text: 'Tue - 20 Mar, 2018', open: 1517443200, close: 1517529599 },
                        { text: 'Wed - 21 Mar, 2018', open: 1517529600, close: 1517615999 },
                    ],
                    trade_types: {
                        'CALL': 'Higher',
                        'PUT': 'Lower',
                    },
                    barriers: {
                        intraday: {
                            high_barrier: '+2.12',
                            low_barrier : '-1.12',
                        },
                        daily: {
                            high_barrier: 1111,
                            low_barrier : 1093,
                        }
                    }
                }
                */

                if (contract.start_type === 'spot') {
                    available_contract_types[type].config.has_spot = 1;
                }

                if (contract.min_contract_duration && contract.max_contract_duration) {
                    available_contract_types[type].config.durations =
                        buildDurationConfig(available_contract_types[type].config.durations, contract);
                }

                if (contract.forward_starting_options) {
                    const forward_starting_options = [];

                    // TODO: handle multiple sessions (right now will create duplicated items in the list)
                    contract.forward_starting_options.forEach(option => {
                        forward_starting_options.push({
                            text : moment.unix(option.open).format('ddd - DD MMM, YYYY'),
                            value: option.open,
                            end  : option.close,
                        });
                    });

                    available_contract_types[type].config.forward_starting_dates = forward_starting_options;
                }

                if (contract.contract_display && contract.contract_type) {
                    const trade_types = available_contract_types[type].config.trade_types || {};

                    trade_types[contract.contract_type] = contract.contract_display;

                    available_contract_types[type].config.trade_types = trade_types;
                }

                if (contract.barriers) {
                    if (!available_contract_types[type].config.barriers) {
                        available_contract_types[type].config.barriers = {};
                    }
                    if (!available_contract_types[type].config.barriers[contract.expiry_type]) {
                        available_contract_types[type].config.barriers[contract.expiry_type] = {};
                    }
                    const obj_barrier = {};
                    if (contract.barrier) {
                        obj_barrier.barrier = contract.barrier;
                    } else {
                        if (contract.low_barrier) {
                            obj_barrier.low_barrier = contract.low_barrier;
                        }
                        if (contract.high_barrier) {
                            obj_barrier.high_barrier = contract.high_barrier;
                        }
                    }
                    available_contract_types[type].config.barriers[contract.expiry_type] = obj_barrier;
                }

            }
        });

        // cleanup categories
        Object.keys(available_categories).forEach((key) => {
            available_categories[key] = available_categories[key].filter(item => typeof item === 'object');
            if (available_categories[key].length === 0) {
                delete available_categories[key];
            }
        });
    });

    const getContractValues = (contract_type, contract_expiry_type, duration_unit) => {
        const form_components   = getComponents(contract_type);
        const obj_trade_types   = getTradeTypes(contract_type);
        const obj_start_dates   = getStartDates(contract_type);
        const obj_start_type    = getStartType(obj_start_dates.start_date);
        const obj_barrier       = getBarriers(contract_type, contract_expiry_type);
        const obj_duration_unit = getDurationUnit(duration_unit, contract_type, obj_start_type.contract_start_type);

        const obj_duration_units_list = getDurationUnitsList(contract_type, obj_start_type.contract_start_type);

        return {
            ...form_components,
            ...obj_trade_types,
            ...obj_start_dates,
            ...obj_start_type,
            ...obj_barrier,
            ...obj_duration_units_list,
            ...obj_duration_unit,
        };
    };

    const getContractType = (list, contract_type) => {
        const list_arr = Object.keys(list || {})
            .reduce((k, l) => ([...k, ...list[l].map(ct => ct.value)]), []);
        return {
            contract_type: list_arr.indexOf(contract_type) === -1 || !contract_type ? list_arr[0] : contract_type,
        };
    };

    const getComponents = (c_type) => ({ form_components: contract_types[c_type].components });

    const getDurationUnitsList = (contract_type, contract_start_type) => {
        const duration_units_list = getPropertyValue(available_contract_types, [contract_type, 'config', 'durations', 'units_display', contract_start_type]) || [];

        return { duration_units_list };
    };

    const getDurationUnit = (duration_unit, contract_type, contract_start_type) => {
        const duration_units = getPropertyValue(available_contract_types, [contract_type, 'config', 'durations', 'units_display', contract_start_type]) || [];
        const arr_units = [];
        duration_units.forEach(obj => {
            arr_units.push(obj.value);
        });

        return {
            duration_unit: (!duration_unit || arr_units.indexOf(duration_unit) === -1) ?
                arr_units[0] : duration_unit,
        };
    };

    // TODO: use this getter function to dynamically compare min/max versus duration amount
    const getDurationMinMax = (contract_type, contract_start_type, contract_expiry_type) => {
        const duration_min_max = getPropertyValue(available_contract_types, [contract_type, 'config', 'durations', 'min_max', contract_start_type, contract_expiry_type]) || {};

        return { duration_min_max };
    };

    const getStartType = (start_date) => {
        const contract_start_type = start_date === 'now' ? 'spot' : 'forward';

        return { contract_start_type };
    };

    const getStartDates = (contract_type) => {
        const config           = getPropertyValue(available_contract_types, [contract_type, 'config']);
        const start_dates_list = [];

        if (config.has_spot) {
            start_dates_list.push({ text: localize('Now'), value: 'now' });
        }
        if (config.forward_starting_dates) {
            start_dates_list.push(...config.forward_starting_dates);
        }

        const start_date = start_dates_list[0].value;

        return { start_date, start_dates_list };
    };

    const getTradeTypes = (contract_type) => ({
        trade_types: getPropertyValue(available_contract_types, [contract_type, 'config', 'trade_types']),
    });

    const getBarriers = (contract_type, expiry_type) => {
        const barriers  = getPropertyValue(available_contract_types, [contract_type, 'config', 'barriers', expiry_type]) || {};
        const barrier_1 = barriers.barrier || barriers.high_barrier || '';
        const barrier_2 = barriers.low_barrier || '';
        return {
            barrier_1: barrier_1.toString(),
            barrier_2: barrier_2.toString(),
        };
    };

    return {
        buildContractTypesConfig,
        getContractValues,
        getContractType,
        getDurationUnitsList,
        getDurationUnit,
        getDurationMinMax,
        getStartType,
        getBarriers,

        getContractCategories: () => available_categories,
    };
})();

const Exceptions = (() => {
    const isIDLanguage = () => getLanguage() === 'ID';

    // if the exception value is true, then it is excluded
    const exceptions = {
        even_odd  : isIDLanguage,
        over_under: isIDLanguage,
    };

    return {
        isExcluded: key => exceptions[key] ? exceptions[key]() : false,
    };
})();

export default ContractType;
<commit_msg>Ignore unsupported contract types<commit_after>import moment from 'moment';
import DAO from '../../../../data/dao';
import { cloneObject, getPropertyValue } from '../../../../../_common/utility';
import { localize } from '../../../../../_common/localize';
import { get as getLanguage } from '../../../../../_common/language';
import { buildDurationConfig } from './duration';

const ContractType = (() => {
    /**
     * components can be undef or an array containing any of: 'start_date', 'barrier', 'last_digit'
     *     ['duration', 'amount'] are omitted, as they're available in all contract types
     */
    const contract_types = {
        rise_fall  : { title: localize('Rise/Fall'),                  trade_types: ['CALL', 'PUT'],               components: ['start_date'], barrier_count: 0 },
        high_low   : { title: localize('Higher/Lower'),               trade_types: ['CALL', 'PUT'],               components: ['barrier'],    barrier_count: 1 },
        touch      : { title: localize('Touch/No Touch'),             trade_types: ['ONETOUCH', 'NOTOUCH'],       components: ['barrier'] },
        end        : { title: localize('Ends Between/Ends Outside'),  trade_types: ['EXPIRYMISS', 'EXPIRYRANGE'], components: ['barrier'] },
        stay       : { title: localize('Stays Between/Goes Outside'), trade_types: ['RANGE', 'UPORDOWN'],         components: ['barrier'] },
        asian      : { title: localize('Asians'),                     trade_types: ['ASIANU', 'ASIAND'],          components: [] },
        match_diff : { title: localize('Matches/Differs'),            trade_types: ['DIGITMATCH', 'DIGITDIFF'],   components: ['last_digit'] },
        even_odd   : { title: localize('Even/Odd'),                   trade_types: ['DIGITODD', 'DIGITEVEN'],     components: [] },
        over_under : { title: localize('Over/Under'),                 trade_types: ['DIGITOVER', 'DIGITUNDER'],   components: ['last_digit'] },
        lb_call    : { title: localize('High-Close'),                 trade_types: ['LBFLOATCALL'],               components: [] },
        lb_put     : { title: localize('Close-Low'),                  trade_types: ['LBFLOATPUT'],                components: [] },
        lb_high_low: { title: localize('High-Low'),                   trade_types: ['LBHIGHLOW'],                 components: [] },
    };

    const contract_categories = {
        [localize('Up/Down')]       : ['rise_fall', 'high_low'],
        [localize('Touch/No Touch')]: ['touch'],
        [localize('In/Out')]        : ['end', 'stay'],
        [localize('Asians')]        : ['asian'],
        [localize('Digits')]        : ['match_diff', 'even_odd', 'over_under'],
        [localize('Lookback')]      : ['lb_call', 'lb_put', 'lb_high_low'],
    };

    let available_contract_types = {};
    let available_categories     = {};

    const buildContractTypesConfig = (symbol) => DAO.getContractsFor(symbol).then(r => {
        available_contract_types = {};
        available_categories = cloneObject(contract_categories); // To preserve the order (will clean the extra items later in this function)
        r.contracts_for.available.forEach((contract) => {
            const type = Object.keys(contract_types).find(key => (
                contract_types[key].trade_types.indexOf(contract.contract_type) !== -1 &&
                (typeof contract_types[key].barrier_count === 'undefined' || +contract_types[key].barrier_count === contract.barriers) // To distinguish betweeen Rise/Fall & Higher/Lower
            ));
            if (!type) return; // ignore unsupported contract types

            if (!Exceptions.isExcluded(type)) {
                if (!available_contract_types[type]) {
                    // extend contract_categories to include what is needed to create the contract list
                    const sub_cats = available_categories[Object.keys(available_categories)
                        .find(key => available_categories[key].indexOf(type) !== -1)];
                    sub_cats[sub_cats.indexOf(type)] = { value: type, text: localize(contract_types[type].title) };

                    // populate available contract types
                    available_contract_types[type]        = cloneObject(contract_types[type]);
                    available_contract_types[type].config = {};
                }

                /*
                add to this config if a value you are looking for does not exist yet
                accordingly create a function to retrieve the value
                config: {
                    has_spot: 1,
                    durations: {
                        min_max: {
                            spot: {
                                tick: {
                                    min: 5, // value in ticks, as cannot convert to seconds
                                    max: 10,
                                },
                                intraday: {
                                    min: 18000, // all values converted to seconds
                                    max: 86400,
                                },
                                daily: {
                                    min: 86400,
                                    max: 432000,
                                },
                            },
                            forward: {
                                intraday: {
                                    min: 18000,
                                    max: 86400,
                                },
                            },
                        },
                        units_display: {
                            spot: [
                                { text: 'ticks', value: 't' },
                                { text: 'seconds', value: 's' },
                                { text: 'minutes', value: 'm' },
                                { text: 'hours', value: 'h' },
                                { text: 'days', value: 'd' },
                            ],
                            forward: [
                                { text: 'days', value: 'd' },
                            ],
                        },
                    },
                    forward_starting_dates: [
                        { text: 'Mon - 19 Mar, 2018', open: 1517356800, close: 1517443199 },
                        { text: 'Tue - 20 Mar, 2018', open: 1517443200, close: 1517529599 },
                        { text: 'Wed - 21 Mar, 2018', open: 1517529600, close: 1517615999 },
                    ],
                    trade_types: {
                        'CALL': 'Higher',
                        'PUT': 'Lower',
                    },
                    barriers: {
                        intraday: {
                            high_barrier: '+2.12',
                            low_barrier : '-1.12',
                        },
                        daily: {
                            high_barrier: 1111,
                            low_barrier : 1093,
                        }
                    }
                }
                */

                if (contract.start_type === 'spot') {
                    available_contract_types[type].config.has_spot = 1;
                }

                if (contract.min_contract_duration && contract.max_contract_duration) {
                    available_contract_types[type].config.durations =
                        buildDurationConfig(available_contract_types[type].config.durations, contract);
                }

                if (contract.forward_starting_options) {
                    const forward_starting_options = [];

                    // TODO: handle multiple sessions (right now will create duplicated items in the list)
                    contract.forward_starting_options.forEach(option => {
                        forward_starting_options.push({
                            text : moment.unix(option.open).format('ddd - DD MMM, YYYY'),
                            value: option.open,
                            end  : option.close,
                        });
                    });

                    available_contract_types[type].config.forward_starting_dates = forward_starting_options;
                }

                if (contract.contract_display && contract.contract_type) {
                    const trade_types = available_contract_types[type].config.trade_types || {};

                    trade_types[contract.contract_type] = contract.contract_display;

                    available_contract_types[type].config.trade_types = trade_types;
                }

                if (contract.barriers) {
                    if (!available_contract_types[type].config.barriers) {
                        available_contract_types[type].config.barriers = {};
                    }
                    if (!available_contract_types[type].config.barriers[contract.expiry_type]) {
                        available_contract_types[type].config.barriers[contract.expiry_type] = {};
                    }
                    const obj_barrier = {};
                    if (contract.barrier) {
                        obj_barrier.barrier = contract.barrier;
                    } else {
                        if (contract.low_barrier) {
                            obj_barrier.low_barrier = contract.low_barrier;
                        }
                        if (contract.high_barrier) {
                            obj_barrier.high_barrier = contract.high_barrier;
                        }
                    }
                    available_contract_types[type].config.barriers[contract.expiry_type] = obj_barrier;
                }

            }
        });

        // cleanup categories
        Object.keys(available_categories).forEach((key) => {
            available_categories[key] = available_categories[key].filter(item => typeof item === 'object');
            if (available_categories[key].length === 0) {
                delete available_categories[key];
            }
        });
    });

    const getContractValues = (contract_type, contract_expiry_type, duration_unit) => {
        const form_components   = getComponents(contract_type);
        const obj_trade_types   = getTradeTypes(contract_type);
        const obj_start_dates   = getStartDates(contract_type);
        const obj_start_type    = getStartType(obj_start_dates.start_date);
        const obj_barrier       = getBarriers(contract_type, contract_expiry_type);
        const obj_duration_unit = getDurationUnit(duration_unit, contract_type, obj_start_type.contract_start_type);

        const obj_duration_units_list = getDurationUnitsList(contract_type, obj_start_type.contract_start_type);

        return {
            ...form_components,
            ...obj_trade_types,
            ...obj_start_dates,
            ...obj_start_type,
            ...obj_barrier,
            ...obj_duration_units_list,
            ...obj_duration_unit,
        };
    };

    const getContractType = (list, contract_type) => {
        const list_arr = Object.keys(list || {})
            .reduce((k, l) => ([...k, ...list[l].map(ct => ct.value)]), []);
        return {
            contract_type: list_arr.indexOf(contract_type) === -1 || !contract_type ? list_arr[0] : contract_type,
        };
    };

    const getComponents = (c_type) => ({ form_components: contract_types[c_type].components });

    const getDurationUnitsList = (contract_type, contract_start_type) => {
        const duration_units_list = getPropertyValue(available_contract_types, [contract_type, 'config', 'durations', 'units_display', contract_start_type]) || [];

        return { duration_units_list };
    };

    const getDurationUnit = (duration_unit, contract_type, contract_start_type) => {
        const duration_units = getPropertyValue(available_contract_types, [contract_type, 'config', 'durations', 'units_display', contract_start_type]) || [];
        const arr_units = [];
        duration_units.forEach(obj => {
            arr_units.push(obj.value);
        });

        return {
            duration_unit: (!duration_unit || arr_units.indexOf(duration_unit) === -1) ?
                arr_units[0] : duration_unit,
        };
    };

    // TODO: use this getter function to dynamically compare min/max versus duration amount
    const getDurationMinMax = (contract_type, contract_start_type, contract_expiry_type) => {
        const duration_min_max = getPropertyValue(available_contract_types, [contract_type, 'config', 'durations', 'min_max', contract_start_type, contract_expiry_type]) || {};

        return { duration_min_max };
    };

    const getStartType = (start_date) => {
        const contract_start_type = start_date === 'now' ? 'spot' : 'forward';

        return { contract_start_type };
    };

    const getStartDates = (contract_type) => {
        const config           = getPropertyValue(available_contract_types, [contract_type, 'config']);
        const start_dates_list = [];

        if (config.has_spot) {
            start_dates_list.push({ text: localize('Now'), value: 'now' });
        }
        if (config.forward_starting_dates) {
            start_dates_list.push(...config.forward_starting_dates);
        }

        const start_date = start_dates_list[0].value;

        return { start_date, start_dates_list };
    };

    const getTradeTypes = (contract_type) => ({
        trade_types: getPropertyValue(available_contract_types, [contract_type, 'config', 'trade_types']),
    });

    const getBarriers = (contract_type, expiry_type) => {
        const barriers  = getPropertyValue(available_contract_types, [contract_type, 'config', 'barriers', expiry_type]) || {};
        const barrier_1 = barriers.barrier || barriers.high_barrier || '';
        const barrier_2 = barriers.low_barrier || '';
        return {
            barrier_1: barrier_1.toString(),
            barrier_2: barrier_2.toString(),
        };
    };

    return {
        buildContractTypesConfig,
        getContractValues,
        getContractType,
        getDurationUnitsList,
        getDurationUnit,
        getDurationMinMax,
        getStartType,
        getBarriers,

        getContractCategories: () => available_categories,
    };
})();

const Exceptions = (() => {
    const isIDLanguage = () => getLanguage() === 'ID';

    // if the exception value is true, then it is excluded
    const exceptions = {
        even_odd  : isIDLanguage,
        over_under: isIDLanguage,
    };

    return {
        isExcluded: key => exceptions[key] ? exceptions[key]() : false,
    };
})();

export default ContractType;
<|endoftext|>


<commit_before>/**
 *
 *  Web Starter Kit
 *  Copyright 2015 Google Inc. All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License
 *
 */

// jshint esversion: 6
// jshint strict: global

'use strict';

// This gulpfile makes use of new JavaScript features.
// Babel handles this without us having to do anything. It just works.
// You can read more about the new JavaScript features here:
// https://babeljs.io/docs/learn-es2015/

import path from 'path';
import gulp from 'gulp';
import qunit from 'gulp-qunit';
import del from 'del';
import runSequence from 'run-sequence';
import browserify from 'browserify';
import babelify from 'babelify';
import source from 'vinyl-source-stream';
import browserSync from 'browser-sync';
import swPrecache from 'sw-precache';
import gulpLoadPlugins from 'gulp-load-plugins';
import {output as pagespeed} from 'psi';
import pkg from './package.json';

const $ = gulpLoadPlugins();
const reload = browserSync.reload;
const transpiledScripts = '.tmp/scripts';
const transpiledTests = '.tmp/test';
const babelOptions = {
	presets: ['es2015']
};

// Lint JavaScript
gulp.task('lint', () =>
  gulp.src('app/scripts/**/*.js')
    .pipe($.eslint())
    .pipe($.eslint.format())
    .pipe($.if(!browserSync.active, $.eslint.failOnError()))
);

// Optimize images
gulp.task('images', () => {
  gulp.src('app/images/**/*')
    .pipe($.imagemin({ // DEBUG removed $.cache( before imagemin
      progressive: true,
      interlaced: true
    }))
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));

		gulp.src('../third_party/images/**/*')
			.pipe($.imagemin({ // DEBUG removed $.cache( before imagemin
				progressive: true,
				interlaced: true
			}))
			.pipe(gulp.dest('dist/images'))
			.pipe($.size({title: 'product images'}))
}

);

// Copy all files at the root level (app)
gulp.task('copy', () =>
  gulp.src([
    'app/*',
    '!app/*.html',
    'node_modules/apache-server-configs/dist/.htaccess'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'))
    .pipe($.size({title: 'copy'}))
);

// Compile and automatically prefix stylesheets
gulp.task('styles', () => {
  const AUTOPREFIXER_BROWSERS = [
    'ie >= 10',
    'ie_mob >= 10',
    'ff >= 30',
    'chrome >= 34',
    'safari >= 7',
    'opera >= 23',
    'ios >= 7',
    'android >= 4.4',
    'bb >= 10'
  ];

  // For best performance, don't add Sass partials to `gulp.src`
  return gulp.src([
    'app/styles/**/*.scss',
    'app/styles/**/*.css'
  ])
    .pipe($.newer('.tmp/styles'))
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      precision: 10
    }).on('error', $.sass.logError))
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest('.tmp/styles'))
    // Concatenate and minify styles
    .pipe($.if('*.css', $.cssnano()))
    .pipe($.size({title: 'styles'}))
    .pipe($.sourcemaps.write('./'))
    .pipe(gulp.dest('dist/styles'));
});

// Concatenate and minify JavaScript. Optionally transpiles ES2015 code to ES5.
// to enable ES2015 support remove the line `"only": "gulpfile.babel.js",` in the
// `.babelrc` file.

gulp.task('transpile', () => {
    gulp.src('app/scripts/**/*.js')
    .pipe($.newer(transpiledScripts))
    .pipe($.sourcemaps.init())
    .pipe($.babel(babelOptions))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest(transpiledScripts));

    gulp.src('app/test/**/*.js')
    .pipe($.newer(transpiledTests))
    .pipe($.sourcemaps.init())
    .pipe($.babel(babelOptions))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest(transpiledTests));

});

gulp.task('scripts', () => {
  browserify([
    './app/scripts/main.js'
  ], { debug: true })
    .transform(babelify, { presets: ['es2015'] })
    .bundle()
    .pipe(source('main.min.js'))
    .on('error', err => { console.log('ERROR:', err.message); })
    .pipe(gulp.dest('dist/scripts/'));
});

// Scan your HTML for assets & optimize them
gulp.task('html', () => {
  return gulp.src('app/**/*.html')
    .pipe($.useref({
      searchPath: '{.tmp,app}',
      noAssets: true
    }))

    // Minify any HTML
    .pipe($.if('*.html', $.htmlmin({
      removeComments: true,
      collapseWhitespace: true,
      collapseBooleanAttributes: true,
      removeAttributeQuotes: true,
      removeRedundantAttributes: true,
      removeEmptyAttributes: true,
      removeScriptTypeAttributes: true,
      removeStyleLinkTypeAttributes: true,
      removeOptionalTags: true
    })))
    // Output files
    .pipe($.if('*.html', $.size({title: 'html', showFiles: true})))
    .pipe(gulp.dest('dist'));
});

// Clean output directory
gulp.task('clean', () => del(['.tmp', 'dist/*', '!dist/.git'], {dot: true}));

// Run unit tests
gulp.task('copy test harness', function() {
  return gulp.src(['app/test/*.html'])
      .pipe(gulp.dest('.tmp/test'));
});

gulp.task('test', ['transpile', 'copy test harness'], function() {
  return gulp.src('.tmp/test/test-runner.html')
      .pipe(qunit());
});

// Watch files for changes & reload
gulp.task('serve', ['scripts', 'styles'], () => {
  browserSync({
    notify: false,
    // Customize the Browsersync console logging prefix
    logPrefix: 'WSK',
    // Allow scroll syncing across breakpoints
    scrollElementMapping: ['main', '.mdl-layout'],
    // Run as an https by uncommenting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    // https: true,
    server: ['.tmp', 'app'],
    port: 3000
  });

  gulp.watch(['app/**/*.html'], reload);
  gulp.watch(['app/styles/**/*.{scss,css}'], ['styles', reload]);
  gulp.watch(['app/scripts/**/*.js'], ['lint', 'scripts', reload]);
  gulp.watch(['app/images/**/*'], reload);
});

// Build and serve the output from the dist build
gulp.task('serve:dist', ['default'], () =>
  browserSync({
    notify: false,
    logPrefix: 'WSK',
    // Allow scroll syncing across breakpoints
    scrollElementMapping: ['main', '.mdl-layout'],
    // Run as an https by uncommenting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    // https: true,
    server: 'dist',
    port: 3001,
		middleware: [(req, res, next) => {
			const url = require('url');
    	let urlObj = url.parse(req.url, true),
        method = req.method;
		  if (method !== 'POST' || urlObj.path !== '/checkout' ) {
				next();
			} else {
				// process POST /checkout
				res.writeHead(200, {'Content-Type': 'text/html'});
				res.end('
Success
');
			}
    }]
  })
);

// Build production files, the default task
gulp.task('default', ['clean'], cb =>
  runSequence(
    'styles',
    ['html', 'scripts', 'images', 'copy'],
    // ['lint', 'html', 'scripts', 'images', 'copy'],
    'generate-service-worker',
    cb
  )
);

// Run PageSpeed Insights
gulp.task('pagespeed', cb =>
  // Update the below URL to the public URL of your site
  pagespeed('example.com', {
    strategy: 'mobile'
    // By default we use the PageSpeed Insights free (no API key) tier.
    // Use a Google Developer API key if you have one: http://goo.gl/RkN0vE
    // key: 'YOUR_API_KEY'
  }, cb)
);

// Copy over the scripts that are used in importScripts as part of the generate-service-worker task.
gulp.task('copy-sw-scripts', () => {
  return gulp.src(['node_modules/sw-toolbox/sw-toolbox.js', 'app/scripts/sw/runtime-caching.js'])
    .pipe(gulp.dest('dist/scripts/sw'));
});

// See http://www.html5rocks.com/en/tutorials/service-worker/introduction/ for
// an in-depth explanation of what service workers are and why you should care.
// Generate a service worker file that will provide offline functionality for
// local resources. This should only be done for the 'dist' directory, to allow
// live reload to work as expected when serving from the 'app' directory.
gulp.task('generate-service-worker', ['copy-sw-scripts'], () => {
  const rootDir = 'dist';
  const filepath = path.join(rootDir, 'service-worker.js');

  return swPrecache.write(filepath, {
    // Used to avoid cache conflicts when serving on localhost.
    cacheId: pkg.name || 'web-starter-kit',
    // sw-toolbox.js needs to be listed first. It sets up methods used in runtime-caching.js.
    importScripts: [
      'scripts/sw/sw-toolbox.js',
      'scripts/sw/runtime-caching.js'
    ],
    staticFileGlobs: [
      // Add/remove glob patterns to match your directory setup.
      `${rootDir}/images/**/*`,
      `${rootDir}/scripts/**/*.js`,
      `${rootDir}/styles/**/*.css`,
      `${rootDir}/*.{html,json}`
    ],
    // Translates a static file path to the relative URL that it's served from.
    // This is '/' rather than path.sep because the paths returned from
    // glob always use '/'.
    stripPrefix: rootDir + '/'
  });
});

// Load custom tasks from the `tasks` directory
// Run: `npm install --save-dev require-dir` from the command-line
// try { require('require-dir')('tasks'); } catch (err) { console.error(err); }
<commit_msg>Always serve from dist due to browersify change<commit_after>/**
 *
 *  Web Starter Kit
 *  Copyright 2015 Google Inc. All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License
 *
 */

// jshint esversion: 6
// jshint strict: global

'use strict';

// This gulpfile makes use of new JavaScript features.
// Babel handles this without us having to do anything. It just works.
// You can read more about the new JavaScript features here:
// https://babeljs.io/docs/learn-es2015/

import path from 'path';
import gulp from 'gulp';
import qunit from 'gulp-qunit';
import del from 'del';
import runSequence from 'run-sequence';
import browserify from 'browserify';
import babelify from 'babelify';
import source from 'vinyl-source-stream';
import browserSync from 'browser-sync';
import swPrecache from 'sw-precache';
import gulpLoadPlugins from 'gulp-load-plugins';
import {output as pagespeed} from 'psi';
import pkg from './package.json';

const $ = gulpLoadPlugins();
const reload = browserSync.reload;
const transpiledScripts = '.tmp/scripts';
const transpiledTests = '.tmp/test';
const babelOptions = {
	presets: ['es2015']
};

// Lint JavaScript
gulp.task('lint', () =>
  gulp.src('app/scripts/**/*.js')
    .pipe($.eslint())
    .pipe($.eslint.format())
    .pipe($.if(!browserSync.active, $.eslint.failOnError()))
);

// Optimize images
gulp.task('images', () => {
  gulp.src('app/images/**/*')
    .pipe($.imagemin({ // DEBUG removed $.cache( before imagemin
      progressive: true,
      interlaced: true
    }))
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));

		gulp.src('../third_party/images/**/*')
			.pipe($.imagemin({ // DEBUG removed $.cache( before imagemin
				progressive: true,
				interlaced: true
			}))
			.pipe(gulp.dest('dist/images'))
			.pipe($.size({title: 'product images'}))
}

);

// Copy all files at the root level (app)
gulp.task('copy', () =>
  gulp.src([
    'app/*',
    '!app/*.html',
    'node_modules/apache-server-configs/dist/.htaccess'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'))
    .pipe($.size({title: 'copy'}))
);

// Compile and automatically prefix stylesheets
gulp.task('styles', () => {
  const AUTOPREFIXER_BROWSERS = [
    'ie >= 10',
    'ie_mob >= 10',
    'ff >= 30',
    'chrome >= 34',
    'safari >= 7',
    'opera >= 23',
    'ios >= 7',
    'android >= 4.4',
    'bb >= 10'
  ];

  // For best performance, don't add Sass partials to `gulp.src`
  return gulp.src([
    'app/styles/**/*.scss',
    'app/styles/**/*.css'
  ])
    .pipe($.newer('.tmp/styles'))
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      precision: 10
    }).on('error', $.sass.logError))
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest('.tmp/styles'))
    // Concatenate and minify styles
    .pipe($.if('*.css', $.cssnano()))
    .pipe($.size({title: 'styles'}))
    .pipe($.sourcemaps.write('./'))
    .pipe(gulp.dest('dist/styles'));
});

// Concatenate and minify JavaScript. Optionally transpiles ES2015 code to ES5.
// to enable ES2015 support remove the line `"only": "gulpfile.babel.js",` in the
// `.babelrc` file.

gulp.task('transpile', () => {
    gulp.src('app/scripts/**/*.js')
    .pipe($.newer(transpiledScripts))
    .pipe($.sourcemaps.init())
    .pipe($.babel(babelOptions))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest(transpiledScripts));

    gulp.src('app/test/**/*.js')
    .pipe($.newer(transpiledTests))
    .pipe($.sourcemaps.init())
    .pipe($.babel(babelOptions))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest(transpiledTests));

});

gulp.task('scripts', () => {
  browserify([
    './app/scripts/main.js'
  ], { debug: true })
    .transform(babelify, { presets: ['es2015'] })
    .bundle()
    .pipe(source('main.min.js'))
    .on('error', err => { console.log('ERROR:', err.message); })
    .pipe(gulp.dest('dist/scripts/'));
});

// Scan your HTML for assets & optimize them
gulp.task('html', () => {
  return gulp.src('app/**/*.html')
    .pipe($.useref({
      searchPath: '{.tmp,app}',
      noAssets: true
    }))

    // Minify any HTML
    .pipe($.if('*.html', $.htmlmin({
      removeComments: true,
      collapseWhitespace: true,
      collapseBooleanAttributes: true,
      removeAttributeQuotes: true,
      removeRedundantAttributes: true,
      removeEmptyAttributes: true,
      removeScriptTypeAttributes: true,
      removeStyleLinkTypeAttributes: true,
      removeOptionalTags: true
    })))
    // Output files
    .pipe($.if('*.html', $.size({title: 'html', showFiles: true})))
    .pipe(gulp.dest('dist'));
});

// Clean output directory
gulp.task('clean', () => del(['.tmp', 'dist/*', '!dist/.git'], {dot: true}));

// Run unit tests
gulp.task('copy test harness', function() {
  return gulp.src(['app/test/*.html'])
      .pipe(gulp.dest('.tmp/test'));
});

gulp.task('test', ['transpile', 'copy test harness'], function() {
  return gulp.src('.tmp/test/test-runner.html')
      .pipe(qunit());
});

// Build and serve the output from the dist build
gulp.task('serve', ['default'], () =>
  browserSync({
    notify: false,
    logPrefix: 'WSK',
    // Allow scroll syncing across breakpoints
    scrollElementMapping: ['main', '.mdl-layout'],
    // Run as an https by uncommenting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    // https: true,
    server: 'dist',
    port: 3001,
		middleware: [(req, res, next) => {
			const url = require('url');
    	let urlObj = url.parse(req.url, true),
        method = req.method;
		  if (method !== 'POST' || urlObj.path !== '/checkout' ) {
				next();
			} else {
				// process POST /checkout
				res.writeHead(200, {'Content-Type': 'text/html'});
				res.end('
Success
');
			}
    }]
  })
);

// Build production files, the default task
gulp.task('default', ['clean'], cb =>
  runSequence(
    'styles',
    ['html', 'scripts', 'images', 'copy'],
    // ['lint', 'html', 'scripts', 'images', 'copy'],
    'generate-service-worker',
    cb
  )
);

// Run PageSpeed Insights
gulp.task('pagespeed', cb =>
  // Update the below URL to the public URL of your site
  pagespeed('example.com', {
    strategy: 'mobile'
    // By default we use the PageSpeed Insights free (no API key) tier.
    // Use a Google Developer API key if you have one: http://goo.gl/RkN0vE
    // key: 'YOUR_API_KEY'
  }, cb)
);

// Copy over the scripts that are used in importScripts as part of the generate-service-worker task.
gulp.task('copy-sw-scripts', () => {
  return gulp.src(['node_modules/sw-toolbox/sw-toolbox.js', 'app/scripts/sw/runtime-caching.js'])
    .pipe(gulp.dest('dist/scripts/sw'));
});

// See http://www.html5rocks.com/en/tutorials/service-worker/introduction/ for
// an in-depth explanation of what service workers are and why you should care.
// Generate a service worker file that will provide offline functionality for
// local resources. This should only be done for the 'dist' directory, to allow
// live reload to work as expected when serving from the 'app' directory.
gulp.task('generate-service-worker', ['copy-sw-scripts'], () => {
  const rootDir = 'dist';
  const filepath = path.join(rootDir, 'service-worker.js');

  return swPrecache.write(filepath, {
    // Used to avoid cache conflicts when serving on localhost.
    cacheId: pkg.name || 'web-starter-kit',
    // sw-toolbox.js needs to be listed first. It sets up methods used in runtime-caching.js.
    importScripts: [
      'scripts/sw/sw-toolbox.js',
      'scripts/sw/runtime-caching.js'
    ],
    staticFileGlobs: [
      // Add/remove glob patterns to match your directory setup.
      `${rootDir}/images/**/*`,
      `${rootDir}/scripts/**/*.js`,
      `${rootDir}/styles/**/*.css`,
      `${rootDir}/*.{html,json}`
    ],
    // Translates a static file path to the relative URL that it's served from.
    // This is '/' rather than path.sep because the paths returned from
    // glob always use '/'.
    stripPrefix: rootDir + '/'
  });
});

// Load custom tasks from the `tasks` directory
// Run: `npm install --save-dev require-dir` from the command-line
// try { require('require-dir')('tasks'); } catch (err) { console.error(err); }
<|endoftext|>


<commit_before>$(function () {

    // Captura de Data e Hora
    (function () {
        // Capturar Elementos
        $('input.form-control-datetimepicker').datetimepicker({
            dateFormat : 'dd/mm/yy',
            timeFormat : 'HH:mm:ss'
        });
    })();

});
<commit_msg>Issue #214 Informa novo padrão para calendário<commit_after>$(function () {

    // Captura de Data e Hora
    (function () {
        // Capturar Elementos
        $('input.form-control-datetimepicker').datetimepicker({
            dateFormat : 'dd/mm/y',
            timeFormat : 'HH:mm:ss'
        });
    })();

});
<|endoftext|>


<commit_before>describe('The dataSelectionApiDataSelection factory', function () {
    let $rootScope,
        $q,
        dataSelectionApiDataSelection,
        api,
        mockedApiResponse,
        mockedApiMarkersResponse,
        config;

    beforeEach(function () {
        angular.mock.module(
            'dpDataSelection',
            {
                api: {
                    getByUri: function (uri) {
                        const q = $q.defer();

                        switch (uri) {
                            case 'zwembaden/markers/':
                                q.resolve(mockedApiMarkersResponse);
                                break;
                            default:
                                q.resolve(mockedApiResponse);
                                break;
                        }

                        return q.promise;
                    }
                },
                sharedConfig: {
                    API_ROOT: 'https://api.amsterdam.nl/'
                }
            }
        );

        angular.mock.inject(function (_$rootScope_, _$q_, _dataSelectionApiDataSelection_, _api_) {
            $rootScope = _$rootScope_;
            $q = _$q_;
            dataSelectionApiDataSelection = _dataSelectionApiDataSelection_;
            api = _api_;
        });

        config = {
            MAX_AVAILABLE_PAGES: 100,
            ENDPOINT_PREVIEW: 'zwembaden/',
            ENDPOINT_MARKERS: 'zwembaden/markers/',
            ENDPOINT_DETAIL: 'api_endpoint/zwembaden/',
            PRIMARY_KEY: 'id',
            FILTERS: [
                {
                    slug: 'type',
                    label: 'Type accomodatie'
                }, {
                    slug: 'water',
                    label: 'Watersoort'
                }
            ]
        };

        mockedApiResponse = {
            aggs_list: {
                water: {
                    doc_count: 3,
                    buckets: [
                        {
                            doc_count: 1,
                            key: 'Tropisch'
                        }, {
                            doc_count: 4,
                            key: 'Verwarmd'
                        }, {
                            doc_count: 1,
                            key: 'Koud'
                        }
                    ]
                },
                type: {
                    doc_count: 2,
                    buckets: [
                        {
                            doc_count: 4,
                            key: 'Buitenbad'
                        },
                        {
                            doc_count: 2,
                            key: 'Overdekt'
                        }
                    ]
                }
            },
            object_list: [
                {
                    _openbare_ruimte_naam: 'Binnenkant',
                    huisletter: 'A',
                    huisnummer: '1',
                    huisnummer_toevoeging: '2',
                    ligplaats_id: '',
                    standplaats_id: '0123456',
                    openingstijden: 'Alleen op dinsdag',
                    adres: 'Sneeuwbalweg 24',
                    id: '1'
                }, {
                    _openbare_ruimte_naam: 'Binnenkant',
                    huisletter: 'B',
                    huisnummer: '1',
                    huisnummer_toevoeging: '',
                    ligplaats_id: '0123456',
                    standplaats_id: '',
                    hoofdadres: 'False',
                    status_id: '18',
                    adres: 'Marnixstraat 1',
                    openingstijden: 'Ligt er een beetje aan',
                    id: '2'
                }, {
                    _openbare_ruimte_naam: 'Binnenkant',
                    huisletter: 'C',
                    huisnummer: '1',
                    huisnummer_toevoeging: '2',
                    ligplaats_id: '',
                    standplaats_id: '0123456',
                    hoofdadres: 'True',
                    status_id: '16',
                    openingstijden: 'Alleen op dinsdag',
                    adres: 'Sneeuwbalweg 24',
                    id: '3'
                }, {
                    handelsnaam: 'De Appel',
                    dataset: 'mac',
                    kvk_nummer: '34392003',
                    id: '4'
                }
            ],
            page_count: 2
        };

        spyOn(api, 'getByUri').and.callThrough();
    });

    it('calls the api factory with the active filters, page and shape as searchParams', function () {
        // Without active filters
        dataSelectionApiDataSelection.query(config, 'LIST', {}, 1, 'search', [[12, 3]]);
        expect(api.getByUri).toHaveBeenCalledWith('zwembaden/', { page: 1, dataset: 'ves', shape: '[[3,12]]' });

        // With active filters
        dataSelectionApiDataSelection.query(config, 'TABLE', {water: 'Verwarmd'}, 2);
        expect(api.getByUri).toHaveBeenCalledWith('zwembaden/', {
            water: 'Verwarmd',
            page: 2,
            dataset: 'ves',
            shape: '[]'
        });

        // With yet another page
        let output;
        dataSelectionApiDataSelection.query(config, 'LIST', {}, 9999).then(function (_output_) {
            output = _output_;
        });
        $rootScope.$apply();
        expect(output.data.length).toBe(0);
    });

    it('returns the total number of pages', function () {
        let output;

        dataSelectionApiDataSelection.query(config, 'LIST', {}, 1).then(function (_output_) {
            output = _output_;
        });
        $rootScope.$apply();

        expect(output.numberOfPages).toBe(2);
    });

    describe('the formatFilters process', function () {
        it('orders the filters based on the configuration', function () {
            let output = {};

            dataSelectionApiDataSelection.query(config, 'LIST', {}, 1).then(function (_output_) {
                output = _output_;
            });
            $rootScope.$apply();

            expect(output.filters).toEqual({
                type: {
                    numberOfOptions: 2,
                    options: [
                        {
                            id: 'Buitenbad',
                            label: 'Buitenbad',
                            count: 4
                        },
                        {
                            id: 'Overdekt',
                            label: 'Overdekt',
                            count: 2
                        }
                    ]
                },
                water: {
                    numberOfOptions: 3,
                    options: [
                        {
                            id: 'Tropisch',
                            label: 'Tropisch',
                            count: 1
                        }, {
                            id: 'Verwarmd',
                            label: 'Verwarmd',
                            count: 4
                        }, {
                            id: 'Koud',
                            label: 'Koud',
                            count: 1
                        }
                    ]
                }
            });
        });

        it('won\'t return filters from the configuration that are not part of the API\'s response', function () {
            let output = {};

            // With only one filter in the API response
            delete mockedApiResponse.aggs_list.type;

            dataSelectionApiDataSelection.query(config, 'LIST', {}, 1).then(function (_output_) {
                output = _output_;
            });
            $rootScope.$apply();

            expect(output.filters).toEqual({
                water: {
                    numberOfOptions: 3,
                    options: [
                        {
                            id: 'Tropisch',
                            label: 'Tropisch',
                            count: 1
                        }, {
                            id: 'Verwarmd',
                            label: 'Verwarmd',
                            count: 4
                        }, {
                            id: 'Koud',
                            label: 'Koud',
                            count: 1
                        }
                    ]
                }
            });
        });
    });

    it('processes the results correctly', function () {
        let output = {};

        dataSelectionApiDataSelection.query(config, 'LIST', {}, 1).then(function (_output_) {
            output = _output_;
        });
        $rootScope.$apply();

        expect(output.data.length).toEqual(4);
        expect(output.data[0]).toEqual({
            _links: {
                self: {
                    href: 'https://api.amsterdam.nl/api_endpoint/zwembaden/1/'
                }
            },
            _openbare_ruimte_naam: 'Binnenkant',
            huisletter: 'A',
            huisnummer: '1',
            huisnummer_toevoeging: '2',
            ligplaats_id: '',
            standplaats_id: '0123456',
            openingstijden: 'Alleen op dinsdag',
            adres: 'Sneeuwbalweg 24',
            id: '1'
        });
        expect(output.data[1]).toEqual({
            _links: {
                self: {
                    href: 'https://api.amsterdam.nl/api_endpoint/zwembaden/2/'
                }
            },
            _openbare_ruimte_naam: 'Binnenkant',
            huisletter: 'B',
            huisnummer: '1',
            huisnummer_toevoeging: '',
            ligplaats_id: '0123456',
            standplaats_id: '',
            hoofdadres: 'False',
            status_id: '18',
            adres: 'Marnixstraat 1',
            openingstijden: 'Ligt er een beetje aan',
            id: '2'
        });
        expect(output.data[2]).toEqual({
            _links: {
                self: {
                    href: 'https://api.amsterdam.nl/api_endpoint/zwembaden/3/'
                }
            },
            _openbare_ruimte_naam: 'Binnenkant',
            huisletter: 'C',
            huisnummer: '1',
            huisnummer_toevoeging: '2',
            ligplaats_id: '',
            standplaats_id: '0123456',
            hoofdadres: 'True',
            status_id: '16',
            openingstijden: 'Alleen op dinsdag',
            adres: 'Sneeuwbalweg 24',
            id: '3'
        });
        expect(output.data[3]).toEqual({
            _links: {
                self: {
                    href: 'https://api.amsterdam.nl/handelsregister/maatschappelijkeactiviteit/34392003/'
                }
            },
            handelsnaam: 'De Appel',
            dataset: 'mac',
            kvk_nummer: '34392003',
            id: '4'
        });
    });

    describe('the getMarkers function', function () {
        beforeEach(function () {
            mockedApiMarkersResponse = {
                object_list: [
                    {
                        _source: {
                            centroid: [4.1, 52.1]
                        }
                    }, {
                        _source: {
                            centroid: [4.2, 52.2]
                        }
                    }, {
                        _source: {
                            centroid: [4.3, 52.3]
                        }
                    }
                ]
            };
        });

        it('calls the api factory with the active filters as searchParams', function () {
            // Without filters
            dataSelectionApiDataSelection.getMarkers(config, {});
            $rootScope.$apply();

            expect(api.getByUri).toHaveBeenCalledWith('zwembaden/markers/', {});

            // With filters
            api.getByUri.calls.reset();
            dataSelectionApiDataSelection.getMarkers(config, { water: 'Verwarmd' });

            expect(api.getByUri).toHaveBeenCalledWith(
                'zwembaden/markers/',
                {
                    water: 'Verwarmd'
                }
            );
        });

        it('returns an array of locations [lat, lon]', function () {
            let output = {};

            dataSelectionApiDataSelection.getMarkers(config, {}).then(function (_output_) {
                output = _output_;
            });
            $rootScope.$apply();

            expect(output).toEqual({
                clusterMarkers: [
                    [52.1, 4.1],
                    [52.2, 4.2],
                    [52.3, 4.3]
                ]
            });
        });
    });
});
<commit_msg>DP-5931 fix unittests<commit_after>describe('The dataSelectionApiDataSelection factory', function () {
    let $rootScope,
        $q,
        dataSelectionApiDataSelection,
        api,
        mockedApiResponse,
        mockedApiMarkersResponse,
        config;

    beforeEach(function () {
        angular.mock.module(
            'dpDataSelection',
            {
                api: {
                    getByUri: function (uri) {
                        const q = $q.defer();

                        switch (uri) {
                            case 'zwembaden/markers/':
                                q.resolve(mockedApiMarkersResponse);
                                break;
                            default:
                                q.resolve(mockedApiResponse);
                                break;
                        }

                        return q.promise;
                    }
                },
                sharedConfig: {
                    API_ROOT: 'https://api.amsterdam.nl/'
                }
            }
        );

        angular.mock.inject(function (_$rootScope_, _$q_, _dataSelectionApiDataSelection_, _api_) {
            $rootScope = _$rootScope_;
            $q = _$q_;
            dataSelectionApiDataSelection = _dataSelectionApiDataSelection_;
            api = _api_;
        });

        config = {
            MAX_AVAILABLE_PAGES: 100,
            ENDPOINT_PREVIEW: 'zwembaden/',
            ENDPOINT_MARKERS: 'zwembaden/markers/',
            ENDPOINT_DETAIL: 'api_endpoint/zwembaden/',
            PRIMARY_KEY: 'id',
            FILTERS: [
                {
                    slug: 'type',
                    label: 'Type accomodatie'
                }, {
                    slug: 'water',
                    label: 'Watersoort'
                }
            ]
        };

        mockedApiResponse = {
            aggs_list: {
                water: {
                    doc_count: 3,
                    buckets: [
                        {
                            doc_count: 1,
                            key: 'Tropisch'
                        }, {
                            doc_count: 4,
                            key: 'Verwarmd'
                        }, {
                            doc_count: 1,
                            key: 'Koud'
                        }
                    ]
                },
                type: {
                    doc_count: 2,
                    buckets: [
                        {
                            doc_count: 4,
                            key: 'Buitenbad'
                        },
                        {
                            doc_count: 2,
                            key: 'Overdekt'
                        }
                    ]
                }
            },
            object_list: [
                {
                    _openbare_ruimte_naam: 'Binnenkant',
                    huisletter: 'A',
                    huisnummer: '1',
                    huisnummer_toevoeging: '2',
                    ligplaats_id: '',
                    standplaats_id: '0123456',
                    openingstijden: 'Alleen op dinsdag',
                    adres: 'Sneeuwbalweg 24',
                    id: '1'
                }, {
                    _openbare_ruimte_naam: 'Binnenkant',
                    huisletter: 'B',
                    huisnummer: '1',
                    huisnummer_toevoeging: '',
                    ligplaats_id: '0123456',
                    standplaats_id: '',
                    hoofdadres: 'False',
                    status_id: '18',
                    adres: 'Marnixstraat 1',
                    openingstijden: 'Ligt er een beetje aan',
                    id: '2'
                }, {
                    _openbare_ruimte_naam: 'Binnenkant',
                    huisletter: 'C',
                    huisnummer: '1',
                    huisnummer_toevoeging: '2',
                    ligplaats_id: '',
                    standplaats_id: '0123456',
                    hoofdadres: 'True',
                    status_id: '16',
                    openingstijden: 'Alleen op dinsdag',
                    adres: 'Sneeuwbalweg 24',
                    id: '3'
                }, {
                    handelsnaam: 'De Appel',
                    dataset: 'mac',
                    kvk_nummer: '34392003',
                    id: '4'
                }
            ],
            page_count: 2
        };

        spyOn(api, 'getByUri').and.callThrough();
    });

    it('calls the api factory with the active filters, page and shape as searchParams', function () {
        // Without active filters
        dataSelectionApiDataSelection.query(config, 'LIST', {}, 1, 'search', [[12, 3]]);
        expect(api.getByUri).toHaveBeenCalledWith('zwembaden/', { page: 1, dataset: 'ves', shape: '[[3,12]]' });

        // With active filters
        dataSelectionApiDataSelection.query(config, 'TABLE', {water: 'Verwarmd'}, 2);
        expect(api.getByUri).toHaveBeenCalledWith('zwembaden/', {
            water: 'Verwarmd',
            page: 2,
            dataset: 'ves',
            shape: '[]'
        });

        // With yet another page
        let output;
        dataSelectionApiDataSelection.query(config, 'LIST', {}, 9999).then(function (_output_) {
            output = _output_;
        });
        $rootScope.$apply();
        expect(output.data.length).toBe(0);
    });

    it('returns the total number of pages', function () {
        let output;

        dataSelectionApiDataSelection.query(config, 'LIST', {}, 1).then(function (_output_) {
            output = _output_;
        });
        $rootScope.$apply();

        expect(output.numberOfPages).toBe(2);
    });

    describe('the formatFilters process', function () {
        it('orders the filters based on the configuration', function () {
            let output = {};

            dataSelectionApiDataSelection.query(config, 'LIST', {}, 1).then(function (_output_) {
                output = _output_;
            });
            $rootScope.$apply();

            expect(output.filters).toEqual({
                type: {
                    numberOfOptions: 2,
                    options: [
                        {
                            id: 'Buitenbad',
                            label: 'Buitenbad',
                            count: 4
                        },
                        {
                            id: 'Overdekt',
                            label: 'Overdekt',
                            count: 2
                        }
                    ]
                },
                water: {
                    numberOfOptions: 3,
                    options: [
                        {
                            id: 'Tropisch',
                            label: 'Tropisch',
                            count: 1
                        }, {
                            id: 'Verwarmd',
                            label: 'Verwarmd',
                            count: 4
                        }, {
                            id: 'Koud',
                            label: 'Koud',
                            count: 1
                        }
                    ]
                }
            });
        });

        it('won\'t return filters from the configuration that are not part of the API\'s response', function () {
            let output = {};

            // With only one filter in the API response
            delete mockedApiResponse.aggs_list.type;

            dataSelectionApiDataSelection.query(config, 'LIST', {}, 1).then(function (_output_) {
                output = _output_;
            });
            $rootScope.$apply();

            expect(output.filters).toEqual({
                water: {
                    numberOfOptions: 3,
                    options: [
                        {
                            id: 'Tropisch',
                            label: 'Tropisch',
                            count: 1
                        }, {
                            id: 'Verwarmd',
                            label: 'Verwarmd',
                            count: 4
                        }, {
                            id: 'Koud',
                            label: 'Koud',
                            count: 1
                        }
                    ]
                }
            });
        });
    });

    it('processes the results correctly', function () {
        let output = {};

        dataSelectionApiDataSelection.query(config, 'LIST', {}, 1).then(function (_output_) {
            output = _output_;
        });
        $rootScope.$apply();

        expect(output.data.length).toEqual(4);
        expect(output.data[0]).toEqual({
            _links: {
                self: {
                    href: 'https://api.amsterdam.nl/api_endpoint/zwembaden/1/'
                }
            },
            _openbare_ruimte_naam: 'Binnenkant',
            huisletter: 'A',
            huisnummer: '1',
            huisnummer_toevoeging: '2',
            ligplaats_id: '',
            standplaats_id: '0123456',
            openingstijden: 'Alleen op dinsdag',
            adres: 'Sneeuwbalweg 24',
            id: '1'
        });
        expect(output.data[1]).toEqual({
            _links: {
                self: {
                    href: 'https://api.amsterdam.nl/api_endpoint/zwembaden/2/'
                }
            },
            _openbare_ruimte_naam: 'Binnenkant',
            huisletter: 'B',
            huisnummer: '1',
            huisnummer_toevoeging: '',
            ligplaats_id: '0123456',
            standplaats_id: '',
            hoofdadres: 'False',
            status_id: '18',
            adres: 'Marnixstraat 1',
            openingstijden: 'Ligt er een beetje aan',
            id: '2'
        });
        expect(output.data[2]).toEqual({
            _links: {
                self: {
                    href: 'https://api.amsterdam.nl/api_endpoint/zwembaden/3/'
                }
            },
            _openbare_ruimte_naam: 'Binnenkant',
            huisletter: 'C',
            huisnummer: '1',
            huisnummer_toevoeging: '2',
            ligplaats_id: '',
            standplaats_id: '0123456',
            hoofdadres: 'True',
            status_id: '16',
            openingstijden: 'Alleen op dinsdag',
            adres: 'Sneeuwbalweg 24',
            id: '3'
        });
        expect(output.data[3]).toEqual({
            _links: {
                self: {
                    href: 'https://api.amsterdam.nl/handelsregister/maatschappelijkeactiviteit/34392003/'
                }
            },
            handelsnaam: 'De Appel',
            dataset: 'mac',
            kvk_nummer: '34392003',
            id: '4'
        });
    });

    describe('the getMarkers function', function () {
        beforeEach(function () {
            mockedApiMarkersResponse = {
                object_list: [
                    {
                        _source: {
                            centroid: [4.1, 52.1]
                        }
                    }, {
                        _source: {
                            centroid: [4.2, 52.2]
                        }
                    }, {
                        _source: {
                            centroid: [4.3, 52.3]
                        }
                    }
                ]
            };
        });

        it('calls the api factory with the active filters as searchParams', function () {
            // Without filters
            dataSelectionApiDataSelection.getMarkers(config, {});
            $rootScope.$apply();

            expect(api.getByUri).toHaveBeenCalledWith('zwembaden/markers/', {});

            // With filters
            api.getByUri.calls.reset();
            dataSelectionApiDataSelection.getMarkers(config, { water: 'Verwarmd' });

            expect(api.getByUri).toHaveBeenCalledWith(
                'zwembaden/markers/',
                {
                    water: 'Verwarmd'
                }
            );
        });

        it('returns an array of locations [lat, lon]', function () {
            let output = {};

            dataSelectionApiDataSelection.getMarkers(config, {}).then(function (_output_) {
                output = _output_;
            });
            $rootScope.$apply();

            expect(output).toEqual({
                clusterMarkers: [
                    {position: [52.1, 4.1]},
                    {position: [52.2, 4.2]},
                    {position: [52.3, 4.3]}
                ]
            });
        });
    });
});
<|endoftext|>


<commit_before>/* @flow */

import * as babel from 'babel-core';
import { SourceMapConsumer } from 'source-map';

import { getCachedModule } from '../babel/lib/moduleSystem';

type LintResults = {
  warnings: { line: number, column: number }[],
};

function toString(templates: string[], expressions: string[]) {
  return templates.reduce(
    (acc, template, i) =>
      `${acc}${template}${i >= expressions.length ? '' : expressions[i]}`,
    ''
  );
}

export default function linariaStylelintPreprocessor(/* options */) {
  process.env.LINARIA_BABEL_PRESET_OVERRIDES = JSON.stringify({
    extract: false,
  });
  // $FlowFixMe
  process.env.LINARIA_COLLECT_RAW_STYLES = true;

  const cache = {};

  return {
    code(input: string, filename: string) {
      const { code, map } = babel.transform(input, {
        filename,
        sourceMaps: true,
      });

      const rawStyles = getCachedModule(
        require.resolve('../sheet.js')
      ).exports.default.rawStyles();

      if (!Object.keys(rawStyles).length || !rawStyles[filename]) {
        return '';
      }

      const css = rawStyles[filename].reduce(
        (acc, { template, expressions, classname }) => {
          const styles = toString(
            template,
            expressions.map(expression => String(expression).replace('\n', ' '))
          );
          return `${acc}\n.${classname} {${styles}}`;
        },
        ''
      );

      cache[filename] = { css, code, map, input };

      return css;
    },
    result(lintResults: LintResults, filename: string) {
      if (!cache[filename]) {
        return;
      }

      const { code, css, map, input } = cache[filename];
      const { warnings } = lintResults;

      warnings.forEach(warning => {
        const relevantCss = css.split('\n').slice(1, warning.line);

        let classname;
        let offset = 0;
        for (let i = relevantCss.length - 1; i >= 0; i--) {
          const match = relevantCss[i].match(/\.(_?[a-zA-Z0-9]+__[a-z0-9]+) {/);
          if (match) {
            classname = match[1];
            offset = relevantCss.length - i - 1;
            break;
          }
        }

        const startLineLocation = code
          .split('\n')
          .findIndex(line => line.includes(classname));
        // prettier-ignore
        const startColumnLocation = code.split('\n')[startLineLocation]
          .indexOf(classname);

        const consumer = new SourceMapConsumer(map);
        const originalPos = consumer.originalPositionFor({
          line: startLineLocation + 1,
          column: startColumnLocation,
        });

        offset += input
          .split('\n')
          .slice(originalPos.line - 1)
          .findIndex(line => /css(\.named\(.+\))?`/.test(line));

        // eslint-disable-next-line no-param-reassign
        warning.line = originalPos.line + offset;
      });
    },
  };
}
<commit_msg>fix: Use relative filename when getting styles in stylelint preprocessor (#191)<commit_after>/* @flow */

import path from 'path';
import * as babel from 'babel-core';
import { SourceMapConsumer } from 'source-map';

import { getCachedModule } from '../babel/lib/moduleSystem';

type LintResults = {
  warnings: { line: number, column: number }[],
};

function toString(templates: string[], expressions: string[]) {
  return templates.reduce(
    (acc, template, i) =>
      `${acc}${template}${i >= expressions.length ? '' : expressions[i]}`,
    ''
  );
}

export default function linariaStylelintPreprocessor(/* options */) {
  process.env.LINARIA_BABEL_PRESET_OVERRIDES = JSON.stringify({
    extract: false,
  });
  // $FlowFixMe
  process.env.LINARIA_COLLECT_RAW_STYLES = true;

  const cache = {};

  return {
    code(input: string, filename: string) {
      const { code, map } = babel.transform(input, {
        filename,
        sourceMaps: true,
      });

      const rawStyles = getCachedModule(
        require.resolve('../sheet.js')
      ).exports.default.rawStyles();

      const relativeFilename = path.relative(process.cwd(), filename);

      if (!Object.keys(rawStyles).length || !rawStyles[relativeFilename]) {
        return '';
      }

      const css = rawStyles[relativeFilename].reduce(
        (acc, { template, expressions, classname }) => {
          const styles = toString(
            template,
            expressions.map(expression => String(expression).replace('\n', ' '))
          );
          return `${acc}\n.${classname} {${styles}}`;
        },
        ''
      );

      cache[filename] = { css, code, map, input };

      return css;
    },
    result(lintResults: LintResults, filename: string) {
      if (!cache[filename]) {
        return;
      }

      const { code, css, map, input } = cache[filename];
      const { warnings } = lintResults;

      warnings.forEach(warning => {
        const relevantCss = css.split('\n').slice(1, warning.line);

        let classname;
        let offset = 0;
        for (let i = relevantCss.length - 1; i >= 0; i--) {
          const match = relevantCss[i].match(/\.(_?[a-zA-Z0-9]+__[a-z0-9]+) {/);
          if (match) {
            classname = match[1];
            offset = relevantCss.length - i - 1;
            break;
          }
        }

        const startLineLocation = code
          .split('\n')
          .findIndex(line => line.includes(classname));
        // prettier-ignore
        const startColumnLocation = code.split('\n')[startLineLocation]
          .indexOf(classname);

        const consumer = new SourceMapConsumer(map);
        const originalPos = consumer.originalPositionFor({
          line: startLineLocation + 1,
          column: startColumnLocation,
        });

        offset += input
          .split('\n')
          .slice(originalPos.line - 1)
          .findIndex(line => /css(\.named\(.+\))?`/.test(line));

        // eslint-disable-next-line no-param-reassign
        warning.line = originalPos.line + offset;
      });
    },
  };
}
<|endoftext|>


<commit_before>var _ = require('lodash'),
    xml = require('xml'),
    config = require('../config'),
    urlService = require('../services/url'),
    common = require('../lib/common'),
    request = require('../lib/request'),
    settingsCache = require('./settings/cache'),

    defaultPostSlugs = [
        'welcome',
        'the-editor',
        'using-tags',
        'managing-users',
        'private-sites',
        'advanced-markdown',
        'themes'
    ],
    // ToDo: Make this configurable
    pingList = [
        {
            url: 'blogsearch.google.com/ping/RPC2'
        },
        {
            url: 'rpc.pingomatic.com'
        }
    ];

function ping(post) {
    var pingXML,
        title = post.title,
        url = urlService.utils.urlFor('post', {post: post}, true);

    if (post.page || config.isPrivacyDisabled('useRpcPing') || settingsCache.get('is_private')) {
        return;
    }

    // Don't ping for the default posts.
    // This also handles the case where during ghost's first run
    // models.init() inserts this post but permissions.init() hasn't
    // (can't) run yet.
    if (defaultPostSlugs.indexOf(post.slug) > -1) {
        return;
    }

    // Build XML object.
    pingXML = xml({
        methodCall: [{
            methodName: 'weblogUpdate.ping'
        }, {
            params: [{
                param: [{
                    value: [{
                        string: title
                    }]
                }]
            }, {
                param: [{
                    value: [{
                        string: url
                    }]
                }]
            }]
        }]
    }, {declaration: true});

    // Ping each of the defined services.
    _.each(pingList, function (pingHost) {
        var options = {
            body: pingXML,
            timeout: 2 * 1000
        };

        request(pingHost.url, options)
            .catch(function (err) {
                common.logging.error(new common.errors.GhostError({
                    err: err,
                    message: err.message,
                    context: common.i18n.t('errors.services.ping.requestFailed.error', {service: 'slack'}),
                    help: common.i18n.t('errors.services.ping.requestFailed.help', {url: 'http://docs.ghost.org'})
                }));
            });
    });
}

function listener(model, options) {
    // CASE: do not rpc ping if we import a database
    // TODO: refactor post.published events to never fire on importing
    if (options && options.importing) {
        return;
    }

    ping(model.toJSON());
}

function listen() {
    common.events.on('post.published', listener);
}

module.exports = {
    listen: listen
};
<commit_msg>Fixed error message for failed xmlrpc request<commit_after>var _ = require('lodash'),
    xml = require('xml'),
    config = require('../config'),
    urlService = require('../services/url'),
    common = require('../lib/common'),
    request = require('../lib/request'),
    settingsCache = require('./settings/cache'),

    defaultPostSlugs = [
        'welcome',
        'the-editor',
        'using-tags',
        'managing-users',
        'private-sites',
        'advanced-markdown',
        'themes'
    ],
    // ToDo: Make this configurable
    pingList = [
        {
            url: 'blogsearch.google.com/ping/RPC2'
        },
        {
            url: 'rpc.pingomatic.com'
        }
    ];

function ping(post) {
    var pingXML,
        title = post.title,
        url = urlService.utils.urlFor('post', {post: post}, true);

    if (post.page || config.isPrivacyDisabled('useRpcPing') || settingsCache.get('is_private')) {
        return;
    }

    // Don't ping for the default posts.
    // This also handles the case where during ghost's first run
    // models.init() inserts this post but permissions.init() hasn't
    // (can't) run yet.
    if (defaultPostSlugs.indexOf(post.slug) > -1) {
        return;
    }

    // Build XML object.
    pingXML = xml({
        methodCall: [{
            methodName: 'weblogUpdate.ping'
        }, {
            params: [{
                param: [{
                    value: [{
                        string: title
                    }]
                }]
            }, {
                param: [{
                    value: [{
                        string: url
                    }]
                }]
            }]
        }]
    }, {declaration: true});

    // Ping each of the defined services.
    _.each(pingList, function (pingHost) {
        var options = {
            body: pingXML,
            timeout: 2 * 1000
        };

        request(pingHost.url, options)
            .catch(function (err) {
                common.logging.error(new common.errors.GhostError({
                    err: err,
                    message: err.message,
                    context: common.i18n.t('errors.services.ping.requestFailed.error', {service: 'xmlrpc'}),
                    help: common.i18n.t('errors.services.ping.requestFailed.help', {url: 'http://docs.ghost.org'})
                }));
            });
    });
}

function listener(model, options) {
    // CASE: do not rpc ping if we import a database
    // TODO: refactor post.published events to never fire on importing
    if (options && options.importing) {
        return;
    }

    ping(model.toJSON());
}

function listen() {
    common.events.on('post.published', listener);
}

module.exports = {
    listen: listen
};
<|endoftext|>


<commit_before>var ResourceService = require("services/ResourceService");
var ItemListService = require("services/ItemListService");

Vue.component("item-search", {

    template: "#vue-item-search",

    props: [],

    data: function()
    {
        return {
            searchString: "",
            itemList: {}
        };
    },

    ready: function()
    {
        ResourceService.bind("itemList", this);
    },

    methods:
    {
        search: function()
        {
            ItemListService.setSearchString(this.searchString);
        }
    }
});
<commit_msg>search page:<commit_after>var ResourceService = require("services/ResourceService");
var ItemListService = require("services/ItemListService");

Vue.component("item-search", {

    template: "#vue-item-search",

    props: [],

    data: function()
    {
        return {
            searchString: "",
            itemList: {}
        };
    },

    ready: function()
    {
        ResourceService.bind("itemList", this);
    },

    methods:
    {
        search: function()
        {
            if (document.location.pathname == "/search")
            {
                ItemListService.setSearchString(this.searchString);
            }
            else
            {
                window.open("/search?searchString=" + this.searchString, "_self", false);
            }
        }
    }
});
<|endoftext|>