<commit_before>var Keychains;
var Wallets;
var coinInstances;

var BaseCoin = function(bitgo, coin) {
  this.bitgo = bitgo;
  this.initializeCoin(coin);

  var self = this;

  this.url = function(suffix) {
    return bitgo._baseUrl + '/api/v2/' + coin + suffix;
  };

  this.wallets = function() {
    if (!self.coinWallets) {
      if (!Wallets) {
        Wallets = require('./wallets');
      }
      self.coinWallets = new Wallets(bitgo, this);
    }
    return self.coinWallets;
  };

  this.keychains = function() {
    if (!self.coinKeychains) {
      if (!Keychains) {
        Keychains = require('./keychains');
      }
      self.coinKeychains = new Keychains(bitgo, this);
    }
    return self.coinKeychains;
  };

};

BaseCoin.prototype.initializeCoin = function(coin) {

  if (!coinInstances) {
    // initialization has to be asynchronous to avoid circular dependencies
    coinInstances = {
      btc: require('./coins/btc'),
      tbtc: require('./coins/tbtc'),
      rmg: require('./coins/rmg'),
      trmg: require('./coins/trmg')
    };
  }

  var coinInstance = coinInstances[coin];
  if (!coinInstance) {
    throw new Error('Coin type ' + coin + ' not supported');
  }
  coinInstance.call(this);

};

BaseCoin.prototype.toJSON = function() {
  return undefined;
};

module.exports = BaseCoin;
<commit_msg>now possible to instantiate a new wallet object from outside in v2<commit_after>var Keychains;
var Wallet;
var Wallets;
var coinInstances;

var BaseCoin = function(bitgo, coin) {
  this.bitgo = bitgo;
  this.initializeCoin(coin);

  var self = this;

  this.url = function(suffix) {
    return bitgo._baseUrl + '/api/v2/' + coin + suffix;
  };

  this.wallets = function() {
    if (!self.coinWallets) {
      if (!Wallets) {
        Wallets = require('./wallets');
      }
      self.coinWallets = new Wallets(bitgo, this);
    }
    return self.coinWallets;
  };

  this.keychains = function() {
    if (!self.coinKeychains) {
      if (!Keychains) {
        Keychains = require('./keychains');
      }
      self.coinKeychains = new Keychains(bitgo, this);
    }
    return self.coinKeychains;
  };

};

BaseCoin.prototype.initializeCoin = function(coin) {

  if (!coinInstances) {
    // initialization has to be asynchronous to avoid circular dependencies
    coinInstances = {
      btc: require('./coins/btc'),
      tbtc: require('./coins/tbtc'),
      rmg: require('./coins/rmg'),
      trmg: require('./coins/trmg')
    };
  }

  var coinInstance = coinInstances[coin];
  if (!coinInstance) {
    throw new Error('Coin type ' + coin + ' not supported');
  }
  coinInstance.call(this);

};

BaseCoin.prototype.newWalletObject = function(walletParams) {
  if (!Wallet) {
    Wallet = require('./wallet');
  }
  return new Wallet(this.bitgo, this, walletParams);
};

BaseCoin.prototype.toJSON = function() {
  return undefined;
};

module.exports = BaseCoin;
<|endoftext|>


<commit_before>/**
 * @author Dmytro Zemlianskyi from Ubrainians for imCode
 * 23.04.19
 */
define(
    'imcms-temporal-data-tab-builder',
    [
        'imcms-super-admin-tab', 'imcms-bem-builder', 'imcms-i18n-texts', 'imcms-temporal-data-rest-api',
        'imcms-components-builder', 'jquery', 'imcms-doc-view-request-api'
    ],
    function (SuperAdminTab, BEM, texts, temporalDataApi, components, $, requestDocView) {

        texts = texts.superAdmin.temporalContent;

        const LOADING_INTERVAL = 2000;
        const TIME_PER_ONE_REINDEX = 45;
        const TIME_PER_ONE_RECACHE = 45;
        const DISABLED_BUTTON_CLASS_NAME = 'imcms-button--disabled';

        function buildActions($button, $date, $loading, $success) {
            return new BEM({
                block: 'actions',
                elements: {
                    'button': $button,
                    'date': $date,
                    'loading': $loading,
                    'success': $success,
                },
            }).buildBlockStructure('<div>');
        }

        class DateLabel {
            constructor(dateRequest, title) {
                this.dateRequest = dateRequest;
                this.title = title;
                this.$label = $('<div>', {
                    class: 'imcms-label',
                    text: title + ':',
                });

                this.updateDate();
            }

            updateDate() {
                this.dateRequest().done(dateString => {
                    this.$label.text(this.title + ': ' + dateString);
                })
            }

            getLabel() {
                return this.$label;
            }
        }

        class TimeLabel {
            constructor(title) {
                this.title = title;
                this.$label = $('<div>', {
                    class: 'imcms-label',
                    text: title + ': ',
                });
            }

            setMillis(millis) {
                this.$label.text(this.title + ': ' + this.millisToTimeString(millis));
            }

            millisToTimeString(millis) {
                let seconds = (millis / 1000);
                let minutes = seconds / 60;
                let hours = minutes / 60;

                seconds = seconds % 60;
                minutes = minutes % 60;

                const correctS = this.numberToCorrectString(Math.round(seconds));
                const correctM = this.numberToCorrectString(Math.round(minutes));
                const correctH = Math.round(hours);

                return correctH + ':' + correctM + ':' + correctS;
            }

            numberToCorrectString(number) {
                return number < 10 ? '0' + number : '' + number;
            }

            getLabel() {
                return this.$label;
            }
        }

        function buildLoadingAnimation() {
            return $('<div>', {
                class: 'loading-animation',
                style: 'display: none',
            });
        }

        function buildSuccessAnimation() {
            return $('<div>', {
                class: 'success-animation',
                style: 'display: none',
            });
        }

        function deleteCacheRequest(request, date, $loading, $success) {
            $success.hide();
            $loading.show();
            request().done(() => {
                date.updateDate();
                $loading.hide();
                $success.show();
            });
        }

        function buildReindexRow() {
            function buildReindexTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.rebuildIndex, {});
            }

            function init($button, date) {
                temporalDataApi.getAmountOfIndexedDocuments().done(currentAmount => {
                    if (currentAmount !== -1) {
                        $button
                            .attr('disabled', '')
                            .text(texts.indexing)
                            .addClass(DISABLED_BUTTON_CLASS_NAME);

                        const interval = setInterval(
                            () => disableButtonWhileIndexing($button, date, interval),
                            LOADING_INTERVAL
                        );
                    }
                });
            }

            function disableButtonWhileIndexing($button, date, interval) {
                temporalDataApi.getAmountOfIndexedDocuments().done(currentAmount => {
                    if (currentAmount === -1) {
                        clearInterval(interval);
                        date.updateDate();
                        $button
                            .removeAttr('disabled')
                            .removeClass(DISABLED_BUTTON_CLASS_NAME)
                            .text(texts.init);
                    }
                });
            }

            function buildReindexActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateDocumentIndex, texts.lastUpdate);
                const timeLeft = new TimeLabel(texts.timeLeft);
                timeLeft.getLabel().hide();

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.initIndexing,
                    click: () => reindexRequest($button, $loading, $success, lastUpdate, timeLeft),
                });

                init($button, lastUpdate);

                return new BEM({
                    block: 'actions',
                    elements: {
                        'button': $button,
                        'date': lastUpdate.getLabel(),
                        'loading': $loading,
                        'success': $success,
                        'time': timeLeft.getLabel(),
                    },
                }).buildBlockStructure('<div>');
            }

            function reindexRequest($button, $loading, $success, date, time) {
                $button
                    .attr('disabled', '')
                    .text(texts.indexing)
                    .addClass(DISABLED_BUTTON_CLASS_NAME);
                $success.hide();

                temporalDataApi.getAmountOfIndexedDocuments().done(currentAmount => {
                    if (currentAmount === -1) {
                        $loading.text('0%');
                        $loading.show();

                        temporalDataApi.rebuildDocumentIndex().done(totalAmount => {
                            time.setMillis(calculateTimeByAmount(totalAmount, 0, TIME_PER_ONE_REINDEX));
                            time.getLabel().show();

                            const interval = setInterval(
                                () => updateLoading($button, $loading, $success, interval, totalAmount, date, time),
                                LOADING_INTERVAL
                            );
                        });
                    } else {
                        const interval = setInterval(
                            () => disableButtonWhileIndexing($button, date, interval),
                            LOADING_INTERVAL
                        );
                    }
                });
            }

            function updateLoading($button, $loading, $success, interval, totalAmount, date, time) {
                temporalDataApi.getAmountOfIndexedDocuments().done(currentAmount => {

                    if (currentAmount === -1) {
                        clearInterval(interval);
                        date.updateDate();
                        $button
                            .removeAttr('disabled')
                            .removeClass(DISABLED_BUTTON_CLASS_NAME)
                            .text(texts.initIndexing);
                        $loading.hide();
                        $success.show();
                        time.getLabel().hide();

                        return;
                    }

                    time.setMillis(calculateTimeByAmount(totalAmount, currentAmount, TIME_PER_ONE_REINDEX));
                    const percent = getPercent(totalAmount, currentAmount);
                    $loading.text(percent + '%');
                });
            }

            function calculateTimeByAmount(totalAmount, currentAmount, timePerOne) {
                return (totalAmount - currentAmount) * timePerOne;
            }

            function getPercent(totalAmount, currentAmount) {
                return Math.round(100 / totalAmount * currentAmount);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildReindexTitleMessage(),
                    'actions': buildReindexActions(),
                }
            }).buildBlockStructure('<div>');
        }

        function buildPublicDocumentCacheRow() {
            function buildPublicDocumentCacheTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.deletePublicDocCache, {});
            }

            function buildPublicDocumentActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateRemoveDocumentCache, texts.lastDeleteCache);

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.init,
                    click: () => deleteCacheRequest(temporalDataApi.deletePublicDocumentCache, lastUpdate, $loading, $success),
                });

                return buildActions($button, lastUpdate.getLabel(), $loading, $success);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildPublicDocumentCacheTitleMessage(),
                    'actions': buildPublicDocumentActions(),
                }
            }).buildBlockStructure('<div>');
        }

        function buildStaticContentRow() {
            function buildStaticContenTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.deleteStaticCache, {});
            }

            function buildInitDeleteStaticContentActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateRemoveStaticContentCache, texts.lastDeleteCache);

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.init,
                    click: () => deleteCacheRequest(temporalDataApi.deleteStaticContentCache, lastUpdate, $loading, $success),
                });

                return buildActions($button, lastUpdate.getLabel(), $loading, $success);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildStaticContenTitleMessage(),
                    'actions': buildInitDeleteStaticContentActions(),
                }
            }).buildBlockStructure('<div>');
        }

        function buildOtherContentRow() {
            function buildOtherContentTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.deleteOtherCache, {});
            }

            function buildInitDeleteOtherContentActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateRemoveOtherContentCache, texts.lastDeleteCache);

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.init,
                    click: () => deleteCacheRequest(temporalDataApi.deleteOtherContentCache, lastUpdate, $loading, $success),
                });

                return buildActions($button, lastUpdate.getLabel(), $loading, $success);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildOtherContentTitleMessage(),
                    'actions': buildInitDeleteOtherContentActions(),
                }
            }).buildBlockStructure('<div>');
        }

        function buildReCacheRow() {
            function buildReCacheTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.buildCacheDocument, {});
            }

            function init($button, date) {
                temporalDataApi.getAmountOfCachedDocuments().done(currentAmount => {
                    if (currentAmount !== -1) {
                        $button
                            .attr('disabled', '')
                            .text(texts.caching)
                            .addClass(DISABLED_BUTTON_CLASS_NAME);

                        const interval = setInterval(
                            () => disableButtonWhileCaching($button, date, interval),
                            LOADING_INTERVAL
                        );
                    }
                });
            }

            function disableButtonWhileCaching($button, date, interval) {
                temporalDataApi.getAmountOfCachedDocuments().done(currentAmount => {
                    if (currentAmount === -1) {
                        clearInterval(interval);
                        date.updateDate();
                        $button
                            .removeAttr('disabled')
                            .removeClass(DISABLED_BUTTON_CLASS_NAME)
                            .text(texts.init);
                    }
                });
            }

            function buildReCacheActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateReCacheDocuments, texts.lastBuildCache);
                const timeLeft = new TimeLabel(texts.timeLeft);
                timeLeft.getLabel().hide();

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.initCaching,
                    click: () => buildCacheRequest($button, $loading, $success, lastUpdate, timeLeft),
                });

                init($button, lastUpdate);

                return new BEM({
                    block: 'actions',
                    elements: {
                        'button': $button,
                        'date': lastUpdate.getLabel(),
                        'loading': $loading,
                        'success': $success,
                        'time': timeLeft.getLabel(),
                    },
                }).buildBlockStructure('<div>');
            }

            function buildCacheRequest($button, $loading, $success, date, time) {
                $button
                    .attr('disabled', '')
                    .text(texts.caching)
                    .addClass(DISABLED_BUTTON_CLASS_NAME);
                $success.hide();

                temporalDataApi.getAmountOfCachedDocuments().done(currentAmount => {
                    if (currentAmount === -1) {
                        $loading.text('0%');
                        $loading.show();
                        temporalDataApi.addDocumentsInCache().done(dataDocInfo => {
                            time.setMillis(calculateTimeByAmount(dataDocInfo.countAvailableDocs, 0, TIME_PER_ONE_RECACHE));
                            time.getLabel().show();

                            const interval = setInterval(
                                () => updateLoading($button, $loading, $success, interval, dataDocInfo.countAvailableDocs, date, time),
                                LOADING_INTERVAL
                            );

                            dataDocInfo.docIds.forEach(docId => {
                                let requestData = {
                                    isReCache: true
                                };
                                requestDocView.simulationDocRequest(docId, requestData).done(

                                );
                            })
                        });

                    } else {
                        const interval = setInterval(
                            () => disableButtonWhileCaching($button, date, interval),
                            LOADING_INTERVAL
                        );
                    }
                });
            }

            function updateLoading($button, $loading, $success, interval, totalAmount, date, time) {
                temporalDataApi.getAmountOfCachedDocuments().done(currentAmount => {

                    if (currentAmount === -1) {
                        clearInterval(interval);
                        date.updateDate();
                        $button
                            .removeAttr('disabled')
                            .removeClass(DISABLED_BUTTON_CLASS_NAME)
                            .text(texts.initCaching);
                        $loading.hide();
                        $success.show();
                        time.getLabel().hide();

                        return;
                    }

                    time.setMillis(calculateTimeByAmount(totalAmount, currentAmount, TIME_PER_ONE_RECACHE));
                    let percent = getPercent(totalAmount, currentAmount);
                    $loading.text(percent + '%');
                });
            }

            function calculateTimeByAmount(totalAmount, currentAmount, timePerOne) {
                return (totalAmount - currentAmount) * timePerOne;
            }

            function getPercent(totalAmount, currentAmount) {
                return Math.round(100 / totalAmount * currentAmount);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildReCacheTitleMessage(),
                    'actions': buildReCacheActions(),
                }
            }).buildBlockStructure('<div>');
        }

        return new SuperAdminTab(texts.name, [
            buildReindexRow(),
            buildPublicDocumentCacheRow(),
            buildStaticContentRow(),
            buildOtherContentRow(),
            buildReCacheRow()
        ]);
    }
);
<commit_msg>Issue IMCMS-505: Button for recache - Comment<commit_after>/**
 * @author Dmytro Zemlianskyi from Ubrainians for imCode
 * 23.04.19
 */
define(
    'imcms-temporal-data-tab-builder',
    [
        'imcms-super-admin-tab', 'imcms-bem-builder', 'imcms-i18n-texts', 'imcms-temporal-data-rest-api',
        'imcms-components-builder', 'jquery', 'imcms-doc-view-request-api'
    ],
    function (SuperAdminTab, BEM, texts, temporalDataApi, components, $, requestDocView) {

        texts = texts.superAdmin.temporalContent;

        const LOADING_INTERVAL = 2000;
        const TIME_PER_ONE_REINDEX = 45;
        const TIME_PER_ONE_RECACHE = 45;
        const DISABLED_BUTTON_CLASS_NAME = 'imcms-button--disabled';

        function buildActions($button, $date, $loading, $success) {
            return new BEM({
                block: 'actions',
                elements: {
                    'button': $button,
                    'date': $date,
                    'loading': $loading,
                    'success': $success,
                },
            }).buildBlockStructure('<div>');
        }

        class DateLabel {
            constructor(dateRequest, title) {
                this.dateRequest = dateRequest;
                this.title = title;
                this.$label = $('<div>', {
                    class: 'imcms-label',
                    text: title + ':',
                });

                this.updateDate();
            }

            updateDate() {
                this.dateRequest().done(dateString => {
                    this.$label.text(this.title + ': ' + dateString);
                })
            }

            getLabel() {
                return this.$label;
            }
        }

        class TimeLabel {
            constructor(title) {
                this.title = title;
                this.$label = $('<div>', {
                    class: 'imcms-label',
                    text: title + ': ',
                });
            }

            setMillis(millis) {
                this.$label.text(this.title + ': ' + this.millisToTimeString(millis));
            }

            millisToTimeString(millis) {
                let seconds = (millis / 1000);
                let minutes = seconds / 60;
                let hours = minutes / 60;

                seconds = seconds % 60;
                minutes = minutes % 60;

                const correctS = this.numberToCorrectString(Math.round(seconds));
                const correctM = this.numberToCorrectString(Math.round(minutes));
                const correctH = Math.round(hours);

                return correctH + ':' + correctM + ':' + correctS;
            }

            numberToCorrectString(number) {
                return number < 10 ? '0' + number : '' + number;
            }

            getLabel() {
                return this.$label;
            }
        }

        function buildLoadingAnimation() {
            return $('<div>', {
                class: 'loading-animation',
                style: 'display: none',
            });
        }

        function buildSuccessAnimation() {
            return $('<div>', {
                class: 'success-animation',
                style: 'display: none',
            });
        }

        function deleteCacheRequest(request, date, $loading, $success) {
            $success.hide();
            $loading.show();
            request().done(() => {
                date.updateDate();
                $loading.hide();
                $success.show();
            });
        }

        function buildReindexRow() {
            function buildReindexTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.rebuildIndex, {});
            }

            function init($button, date) {
                temporalDataApi.getAmountOfIndexedDocuments().done(currentAmount => {
                    if (currentAmount !== -1) {
                        $button
                            .attr('disabled', '')
                            .text(texts.indexing)
                            .addClass(DISABLED_BUTTON_CLASS_NAME);

                        const interval = setInterval(
                            () => disableButtonWhileIndexing($button, date, interval),
                            LOADING_INTERVAL
                        );
                    }
                });
            }

            function disableButtonWhileIndexing($button, date, interval) {
                temporalDataApi.getAmountOfIndexedDocuments().done(currentAmount => {
                    if (currentAmount === -1) {
                        clearInterval(interval);
                        date.updateDate();
                        $button
                            .removeAttr('disabled')
                            .removeClass(DISABLED_BUTTON_CLASS_NAME)
                            .text(texts.init);
                    }
                });
            }

            function buildReindexActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateDocumentIndex, texts.lastUpdate);
                const timeLeft = new TimeLabel(texts.timeLeft);
                timeLeft.getLabel().hide();

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.initIndexing,
                    click: () => reindexRequest($button, $loading, $success, lastUpdate, timeLeft),
                });

                init($button, lastUpdate);

                return new BEM({
                    block: 'actions',
                    elements: {
                        'button': $button,
                        'date': lastUpdate.getLabel(),
                        'loading': $loading,
                        'success': $success,
                        'time': timeLeft.getLabel(),
                    },
                }).buildBlockStructure('<div>');
            }

            function reindexRequest($button, $loading, $success, date, time) {
                $button
                    .attr('disabled', '')
                    .text(texts.indexing)
                    .addClass(DISABLED_BUTTON_CLASS_NAME);
                $success.hide();

                temporalDataApi.getAmountOfIndexedDocuments().done(currentAmount => {
                    if (currentAmount === -1) {
                        $loading.text('0%');
                        $loading.show();

                        temporalDataApi.rebuildDocumentIndex().done(totalAmount => {
                            time.setMillis(calculateTimeByAmount(totalAmount, 0, TIME_PER_ONE_REINDEX));
                            time.getLabel().show();

                            const interval = setInterval(
                                () => updateLoading($button, $loading, $success, interval, totalAmount, date, time),
                                LOADING_INTERVAL
                            );
                        });
                    } else {
                        const interval = setInterval(
                            () => disableButtonWhileIndexing($button, date, interval),
                            LOADING_INTERVAL
                        );
                    }
                });
            }

            function updateLoading($button, $loading, $success, interval, totalAmount, date, time) {
                temporalDataApi.getAmountOfIndexedDocuments().done(currentAmount => {

                    if (currentAmount === -1) {
                        clearInterval(interval);
                        date.updateDate();
                        $button
                            .removeAttr('disabled')
                            .removeClass(DISABLED_BUTTON_CLASS_NAME)
                            .text(texts.initIndexing);
                        $loading.hide();
                        $success.show();
                        time.getLabel().hide();

                        return;
                    }

                    time.setMillis(calculateTimeByAmount(totalAmount, currentAmount, TIME_PER_ONE_REINDEX));
                    const percent = getPercent(totalAmount, currentAmount);
                    $loading.text(percent + '%');
                });
            }

            function calculateTimeByAmount(totalAmount, currentAmount, timePerOne) {
                return (totalAmount - currentAmount) * timePerOne;
            }

            function getPercent(totalAmount, currentAmount) {
                return Math.round(100 / totalAmount * currentAmount);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildReindexTitleMessage(),
                    'actions': buildReindexActions(),
                }
            }).buildBlockStructure('<div>');
        }

        function buildPublicDocumentCacheRow() {
            function buildPublicDocumentCacheTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.deletePublicDocCache, {});
            }

            function buildPublicDocumentActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateRemoveDocumentCache, texts.lastDeleteCache);

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.init,
                    click: () => deleteCacheRequest(temporalDataApi.deletePublicDocumentCache, lastUpdate, $loading, $success),
                });

                return buildActions($button, lastUpdate.getLabel(), $loading, $success);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildPublicDocumentCacheTitleMessage(),
                    'actions': buildPublicDocumentActions(),
                }
            }).buildBlockStructure('<div>');
        }

        function buildStaticContentRow() {
            function buildStaticContenTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.deleteStaticCache, {});
            }

            function buildInitDeleteStaticContentActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateRemoveStaticContentCache, texts.lastDeleteCache);

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.init,
                    click: () => deleteCacheRequest(temporalDataApi.deleteStaticContentCache, lastUpdate, $loading, $success),
                });

                return buildActions($button, lastUpdate.getLabel(), $loading, $success);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildStaticContenTitleMessage(),
                    'actions': buildInitDeleteStaticContentActions(),
                }
            }).buildBlockStructure('<div>');
        }

        function buildOtherContentRow() {
            function buildOtherContentTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.deleteOtherCache, {});
            }

            function buildInitDeleteOtherContentActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateRemoveOtherContentCache, texts.lastDeleteCache);

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.init,
                    click: () => deleteCacheRequest(temporalDataApi.deleteOtherContentCache, lastUpdate, $loading, $success),
                });

                return buildActions($button, lastUpdate.getLabel(), $loading, $success);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildOtherContentTitleMessage(),
                    'actions': buildInitDeleteOtherContentActions(),
                }
            }).buildBlockStructure('<div>');
        }

        function buildReCacheRow() {
            function buildReCacheTitleMessage() {
                return components.texts.titleText('<div>', texts.actions.buildCacheDocument, {});
            }

            function init($button, date) {
                temporalDataApi.getAmountOfCachedDocuments().done(currentAmount => {
                    if (currentAmount !== -1) {
                        $button
                            .attr('disabled', '')
                            .text(texts.caching)
                            .addClass(DISABLED_BUTTON_CLASS_NAME);

                        const interval = setInterval(
                            () => disableButtonWhileCaching($button, date, interval),
                            LOADING_INTERVAL
                        );
                    }
                });
            }

            function disableButtonWhileCaching($button, date, interval) {
                temporalDataApi.getAmountOfCachedDocuments().done(currentAmount => {
                    if (currentAmount === -1) {
                        clearInterval(interval);
                        date.updateDate();
                        $button
                            .removeAttr('disabled')
                            .removeClass(DISABLED_BUTTON_CLASS_NAME)
                            .text(texts.init);
                    }
                });
            }

            function buildReCacheActions() {
                const $loading = buildLoadingAnimation();
                const $success = buildSuccessAnimation();

                const lastUpdate = new DateLabel(temporalDataApi.getDateReCacheDocuments, texts.lastBuildCache);
                const timeLeft = new TimeLabel(texts.timeLeft);
                timeLeft.getLabel().hide();

                const $button = components.buttons.warningButton({
                    'class': 'imcms-buttons imcms-form__field',
                    text: texts.initCaching,
                    click: () => buildCacheRequest($button, $loading, $success, lastUpdate, timeLeft),
                });

                init($button, lastUpdate);

                return new BEM({
                    block: 'actions',
                    elements: {
                        'button': $button,
                        'date': lastUpdate.getLabel(),
                        'loading': $loading,
                        'success': $success,
                        'time': timeLeft.getLabel(),
                    },
                }).buildBlockStructure('<div>');
            }

            function buildCacheRequest($button, $loading, $success, date, time) {
                $button
                    .attr('disabled', '')
                    .text(texts.caching)
                    .addClass(DISABLED_BUTTON_CLASS_NAME);
                $success.hide();

                temporalDataApi.getAmountOfCachedDocuments().done(currentAmount => {
                    if (currentAmount === -1) {
                        $loading.text('0%');
                        $loading.show();
                        temporalDataApi.addDocumentsInCache().done(dataDocInfo => {
                            time.setMillis(calculateTimeByAmount(dataDocInfo.countAvailableDocs, 0, TIME_PER_ONE_RECACHE));
                            time.getLabel().show();

                            const interval = setInterval(
                                () => updateLoading($button, $loading, $success, interval, dataDocInfo.countAvailableDocs, date, time),
                                LOADING_INTERVAL
                            );

                            // dataDocInfo.docIds.forEach(docId => {
                            //     let requestData = {
                            //         isReCache: true
                            //     };
                            //     requestDocView.simulationDocRequest(docId, requestData).done(
                            //
                            //     );
                            // })
                        });

                    } else {
                        const interval = setInterval(
                            () => disableButtonWhileCaching($button, date, interval),
                            LOADING_INTERVAL
                        );
                    }
                });
            }

            function updateLoading($button, $loading, $success, interval, totalAmount, date, time) {
                temporalDataApi.getAmountOfCachedDocuments().done(currentAmount => {

                    if (currentAmount === -1) {
                        clearInterval(interval);
                        date.updateDate();
                        $button
                            .removeAttr('disabled')
                            .removeClass(DISABLED_BUTTON_CLASS_NAME)
                            .text(texts.initCaching);
                        $loading.hide();
                        $success.show();
                        time.getLabel().hide();

                        return;
                    }

                    time.setMillis(calculateTimeByAmount(totalAmount, currentAmount, TIME_PER_ONE_RECACHE));
                    let percent = getPercent(totalAmount, currentAmount);
                    $loading.text(percent + '%');
                });
            }

            function calculateTimeByAmount(totalAmount, currentAmount, timePerOne) {
                return (totalAmount - currentAmount) * timePerOne;
            }

            function getPercent(totalAmount, currentAmount) {
                return Math.round(100 / totalAmount * currentAmount);
            }

            return new BEM({
                block: 'imcms-content-action-row',
                elements: {
                    'action-title': buildReCacheTitleMessage(),
                    'actions': buildReCacheActions(),
                }
            }).buildBlockStructure('<div>');
        }

        return new SuperAdminTab(texts.name, [
            buildReindexRow(),
            buildPublicDocumentCacheRow(),
            buildStaticContentRow(),
            buildOtherContentRow(),
            buildReCacheRow()
        ]);
    }
);
<|endoftext|>


<commit_before>/* global TrelloPowerUp */

var WHITE_ICON = './images/icon-white.svg';
var GRAY_ICON = './images/icon-gray.svg';
var APP_ID = '380ed9c5-4e06-4b73-b2e0-115ab3810cb8';
var DEFAULT = "XXX";

var KEY_ACCESS_TOKEN = "accessToken";
var KEY_ENDPOINT_HINT= "endpointHint";
var KEY_REFRESH_TOKEN = "refreshToken";
var KEY_EXPIRES_IN = "expiresIn";

var parkMap = {
    acad: 'Acadia National Park',
    arch: 'Arches National Park',
    badl: 'Badlands National Park',
    brca: 'Bryce Canyon National Park',
    crla: 'Crater Lake National Park',
    dena: 'Denali National Park',
    glac: 'Glacier National Park',
    grca: 'Grand Canyon National Park',
    grte: 'Grand Teton National Park',
    olym: 'Olympic National Park',
    yell: 'Yellowstone National Park',
    yose: 'Yosemite National Park',
    zion: 'Zion National Park'
};

var getBadges = function (t) {
    return t.card('attachments')
        .get('attachments')
        .then(function (attachments) {

            var cnt = 0;

            var len = attachments.length;
            for (var i = 0; i < len; i++) {
                var name = formatDrawUrl(null, attachments[i].url);
                if (name) {
                    cnt++;
                }
            }

            if (cnt > 0) {
                var badgeColor = 'orange';
                var icon = WHITE_ICON;
                var text = (cnt == 1) ? "1 Drawing" : cnt + " Drawings";

                // return an array of badge objects
                return [{
                    text: text,
                    icon: icon, // for card front badges only
                    color: badgeColor
                }];
            } else {
                return [];
            }
        });
};

var formatNPSUrl = function (t, url) {
    if (!/^https?:\/\/www\.nps\.gov\/[a-z]{4}\//.test(url)) {
        return null;
    }
    var parkShort = /^https?:\/\/www\.nps\.gov\/([a-z]{4})\//.exec(url)[1];
    if (parkShort && parkMap[parkShort]) {
        return parkMap[parkShort];
    } else {
        return null;
    }
};

var boardButtonCallback = function (t) {
    /*return t.popup({
        title: 'Popup List Example',
        items: [
            {
                text: 'Open Overlay',
                callback: function (t) {
                    return t.overlay({
                        url: './overlay.html',
                        args: {rand: (Math.random() * 100).toFixed(0)}
                    })
                        .then(function () {
                            return t.closePopup();
                        });
                }
            },
            {
                text: 'Open Board Bar',
                callback: function (t) {
                    return t.boardBar({
                        url: './board-bar.html',
                        height: 200
                    })
                        .then(function () {
                            return t.closePopup();
                        });
                }
            }
        ]
    });*/

    return t.overlay({
        url: './javascript/editor/grapheditor/www/index.html',
        args: {rand: (Math.random() * 100).toFixed(0)}
    })
        .then(function () {
            return t.closePopup();
        });

};

var cardButtonCallback = function (t) {
    /*var items = Object.keys(parkMap).map(function (parkCode) {
        var urlForCode = 'http://www.nps.gov/' + parkCode + '/';
        return {
            text: parkMap[parkCode],
            url: urlForCode,
            callback: function (t) {
                return t.attach({url: urlForCode, name: parkMap[parkCode]})
                    .then(function () {
                        return t.closePopup();
                    })
            }
        };
    });

    return t.popup({
        title: 'Popup Search Example',
        items: items,
        search: {
            count: 5,
            placeholder: 'Search National Parks',
            empty: 'No parks found'
        }
    });*/

    return t.overlay({
        url: '../index.html',
        args: {rand: (Math.random() * 100).toFixed(0)}
    })
        .then(function () {
            return t.closePopup();
        });

};

TrelloPowerUp.initialize({

    'authorization-status': function(t) {

        /*return t.get('board', 'private', KEY_ACCESS_TOKEN, DEFAULT)
            .then(function (token) {
                console.log(token);

                if(token===DEFAULT) {

                    // if false
                    // `show-authorization` is displayed
                    return new TrelloPowerUp.Promise((resolve) =>
                        resolve({ authorized: false })
                    )
                }
                else {

                    // if true
                    // t.set has been used
                    // `remove settings` is displayed

                    return new TrelloPowerUp.Promise((resolve) =>
                        resolve({ authorized: true })
                    )

                }

            });*/

        return new TrelloPowerUp.Promise((resolve) =>
            resolve({ authorized: true })
        )

    },

    'show-authorization': function(t) {
        return t.popup({
            title: 'Authorize',
            items: [
                {
                    text: "Connect Microsoft or Office 365 Account",
                    callback: function () {
                        console.log("TODO settings auth");
                    }
                }
            ]
        });
    },

    'show-settings': function (t, options) {
        return t.popup({
            title: 'Settings',
            url: './settings.html',
            height: 184
        });
    },

    // Allows you to add one or more buttons on the right side of the back of cards
    // Each button should have { icon, text, callback -> method }
    'card-buttons': function (t, options) {
        return [{
            icon: GRAY_ICON,
            text: 'New Drawing',
            callback: cardButtonCallback
        }];
    },

    'attachment-sections': function (t, options) {

        //console.log(JSON.stringify(options));

        // options.entries is a list of the attachments for this card
        // you can look through them and 'claim' any that you want to
        // include in your section.

        // we will just claim urls for Yellowstone
        var claimed = options.entries.filter(drawFilter);

        // you can have more than one attachment section on a card
        // you can group items together into one section, have a section
        // per attachment, or anything in between.
        if (claimed && claimed.length > 0) {
            // if the title for your section requires a network call or other
            // potentially length operation you can provide a function for the title
            // that returns the section title. If you do so, provide a unique id for
            // your section

            //console.log(JSON.stringify(claimed));

            return [{
                id: BASE_URL, // optional if you aren't using a function for the title
                claimed: claimed,
                icon: GRAY_ICON,
                title: 'Attached Drawings',
                content: {
                    type: 'iframe',
                    url: t.signUrl('./section.html', {arg: claimed}),
                    height: 230
                }
            }];
        } else {
            return [];
        }
    },
    'attachment-thumbnail': function (t, attachment) {
        var name = formatDrawUrl(t, attachment.url);
        if (name) {
            // return an object with some or all of these properties:
            // url, title, image, openText, modified (Date), created (Date), createdBy, modifiedBy
            return {
                title: name,
                url: attachment.url,
                openText: "Open Externally",
                image: {
                    url: './images/icon-gray.svg',
                    logo: true // false if this is a thumbnail
                },
                initialize: {
                    type: 'iframe',
                    url: TrelloPowerUp.util.relativeUrl('./authorize.html')
                }
            };
        } else {
            throw t.NotHandled();
        }
    },

    // Allows you to add one or more buttons to a Board at the top right of the screen
    'board-buttons': function (t, options) {
        return [{
            icon: WHITE_ICON,
            text: 'Office 365',
            callback: boardButtonCallback
        }];
    },

    'card-badges': function (t, card) {
        console.log('card-badges');
        //console.log(JSON.stringify(t));
        //console.log(JSON.stringify(card));
        return getBadges(t);
    },

    'card-detail-badges': function (t, options) {
        return getBadges(t);
    },
    'card-from-url': function (t, options) {
        var parkName = formatNPSUrl(t, options.url);
        if (parkName) {
            return {
                name: parkName,
                desc: 'An awesome park: ' + options.url
            };
        } else {
            throw t.NotHandled();
        }
    },
    'format-url': function (t, options) {
        var name = formatDrawUrl(t, options.url);

        console.log("format-url> "+JSON.stringify(name));

        if (name) {
            return {
                icon: GRAY_ICON,
                text: name
            };
        } else {
            throw t.NotHandled();
        }
    }
});
<commit_msg>card badge<commit_after>/* global TrelloPowerUp */

var WHITE_ICON = './images/icon-white.svg';
var GRAY_ICON = './images/icon-gray.svg';
var APP_ID = '380ed9c5-4e06-4b73-b2e0-115ab3810cb8';
var DEFAULT = "XXX";

var KEY_ACCESS_TOKEN = "accessToken";
var KEY_ENDPOINT_HINT= "endpointHint";
var KEY_REFRESH_TOKEN = "refreshToken";
var KEY_EXPIRES_IN = "expiresIn";

var parkMap = {
    acad: 'Acadia National Park',
    arch: 'Arches National Park',
    badl: 'Badlands National Park',
    brca: 'Bryce Canyon National Park',
    crla: 'Crater Lake National Park',
    dena: 'Denali National Park',
    glac: 'Glacier National Park',
    grca: 'Grand Canyon National Park',
    grte: 'Grand Teton National Park',
    olym: 'Olympic National Park',
    yell: 'Yellowstone National Park',
    yose: 'Yosemite National Park',
    zion: 'Zion National Park'
};

var getBadges = function (t) {
    return t.card('attachments')
        .get('attachments')
        .then(function (attachments) {

            var cnt = 0;

            var len = attachments.length;
            for (var i = 0; i < len; i++) {
                var name = formatDrawUrl(null, attachments[i].url);
                if (name) {
                    cnt++;
                }
            }

            if (cnt > 0) {
                // return an array of badge objects
                return [{
                    text: cnt,
                    icon: WHITE_ICON, // for card front badges only
                    color: 'yellow'
                }];
            } else {
                return [];
            }
        });
};

var formatNPSUrl = function (t, url) {
    if (!/^https?:\/\/www\.nps\.gov\/[a-z]{4}\//.test(url)) {
        return null;
    }
    var parkShort = /^https?:\/\/www\.nps\.gov\/([a-z]{4})\//.exec(url)[1];
    if (parkShort && parkMap[parkShort]) {
        return parkMap[parkShort];
    } else {
        return null;
    }
};

var boardButtonCallback = function (t) {
    /*return t.popup({
        title: 'Popup List Example',
        items: [
            {
                text: 'Open Overlay',
                callback: function (t) {
                    return t.overlay({
                        url: './overlay.html',
                        args: {rand: (Math.random() * 100).toFixed(0)}
                    })
                        .then(function () {
                            return t.closePopup();
                        });
                }
            },
            {
                text: 'Open Board Bar',
                callback: function (t) {
                    return t.boardBar({
                        url: './board-bar.html',
                        height: 200
                    })
                        .then(function () {
                            return t.closePopup();
                        });
                }
            }
        ]
    });*/

    return t.overlay({
        url: './javascript/editor/grapheditor/www/index.html',
        args: {rand: (Math.random() * 100).toFixed(0)}
    })
        .then(function () {
            return t.closePopup();
        });

};

var cardButtonCallback = function (t) {
    /*var items = Object.keys(parkMap).map(function (parkCode) {
        var urlForCode = 'http://www.nps.gov/' + parkCode + '/';
        return {
            text: parkMap[parkCode],
            url: urlForCode,
            callback: function (t) {
                return t.attach({url: urlForCode, name: parkMap[parkCode]})
                    .then(function () {
                        return t.closePopup();
                    })
            }
        };
    });

    return t.popup({
        title: 'Popup Search Example',
        items: items,
        search: {
            count: 5,
            placeholder: 'Search National Parks',
            empty: 'No parks found'
        }
    });*/

    return t.overlay({
        url: '../index.html',
        args: {rand: (Math.random() * 100).toFixed(0)}
    })
        .then(function () {
            return t.closePopup();
        });

};

TrelloPowerUp.initialize({

    'authorization-status': function(t) {

        /*return t.get('board', 'private', KEY_ACCESS_TOKEN, DEFAULT)
            .then(function (token) {
                console.log(token);

                if(token===DEFAULT) {

                    // if false
                    // `show-authorization` is displayed
                    return new TrelloPowerUp.Promise((resolve) =>
                        resolve({ authorized: false })
                    )
                }
                else {

                    // if true
                    // t.set has been used
                    // `remove settings` is displayed

                    return new TrelloPowerUp.Promise((resolve) =>
                        resolve({ authorized: true })
                    )

                }

            });*/

        return new TrelloPowerUp.Promise((resolve) =>
            resolve({ authorized: true })
        )

    },

    'show-authorization': function(t) {
        return t.popup({
            title: 'Authorize',
            items: [
                {
                    text: "Connect Microsoft or Office 365 Account",
                    callback: function () {
                        console.log("TODO settings auth");
                    }
                }
            ]
        });
    },

    'show-settings': function (t, options) {
        return t.popup({
            title: 'Settings',
            url: './settings.html',
            height: 184
        });
    },

    // Allows you to add one or more buttons on the right side of the back of cards
    // Each button should have { icon, text, callback -> method }
    'card-buttons': function (t, options) {
        return [{
            icon: GRAY_ICON,
            text: 'New Drawing',
            callback: cardButtonCallback
        }];
    },

    'attachment-sections': function (t, options) {

        //console.log(JSON.stringify(options));

        // options.entries is a list of the attachments for this card
        // you can look through them and 'claim' any that you want to
        // include in your section.

        // we will just claim urls for Yellowstone
        var claimed = options.entries.filter(drawFilter);

        // you can have more than one attachment section on a card
        // you can group items together into one section, have a section
        // per attachment, or anything in between.
        if (claimed && claimed.length > 0) {
            // if the title for your section requires a network call or other
            // potentially length operation you can provide a function for the title
            // that returns the section title. If you do so, provide a unique id for
            // your section

            //console.log(JSON.stringify(claimed));

            return [{
                id: BASE_URL, // optional if you aren't using a function for the title
                claimed: claimed,
                icon: GRAY_ICON,
                title: 'Attached Drawings',
                content: {
                    type: 'iframe',
                    url: t.signUrl('./section.html', {arg: claimed}),
                    height: 230
                }
            }];
        } else {
            return [];
        }
    },
    'attachment-thumbnail': function (t, attachment) {
        var name = formatDrawUrl(t, attachment.url);
        if (name) {
            // return an object with some or all of these properties:
            // url, title, image, openText, modified (Date), created (Date), createdBy, modifiedBy
            return {
                title: name,
                url: attachment.url,
                openText: "Open Externally",
                image: {
                    url: './images/icon-gray.svg',
                    logo: true // false if this is a thumbnail
                },
                initialize: {
                    type: 'iframe',
                    url: TrelloPowerUp.util.relativeUrl('./authorize.html')
                }
            };
        } else {
            throw t.NotHandled();
        }
    },

    // Allows you to add one or more buttons to a Board at the top right of the screen
    'board-buttons': function (t, options) {
        return [{
            icon: WHITE_ICON,
            text: 'Office 365',
            callback: boardButtonCallback
        }];
    },

    'card-badges': function (t, card) {
        console.log('card-badges');
        //console.log(JSON.stringify(t));
        //console.log(JSON.stringify(card));
        return getBadges(t);
    },

    'card-detail-badges': function (t, options) {
        return getBadges(t);
    },
    'card-from-url': function (t, options) {
        var parkName = formatNPSUrl(t, options.url);
        if (parkName) {
            return {
                name: parkName,
                desc: 'An awesome park: ' + options.url
            };
        } else {
            throw t.NotHandled();
        }
    },
    'format-url': function (t, options) {
        var name = formatDrawUrl(t, options.url);

        console.log("format-url> "+JSON.stringify(name));

        if (name) {
            return {
                icon: GRAY_ICON,
                text: name
            };
        } else {
            throw t.NotHandled();
        }
    }
});
<|endoftext|>


<commit_before>/* global TrelloPowerUp */

var WHITE_ICON = './images/icon-white.svg';
var GRAY_ICON = './images/icon-gray.svg';
var APP_ID = '380ed9c5-4e06-4b73-b2e0-115ab3810cb8';
var DEFAULT = "XXX";

var KEY_ACCESS_TOKEN = "accessToken";
var KEY_ENDPOINT_HINT= "endpointHint";
var KEY_REFRESH_TOKEN = "refreshToken";
var KEY_EXPIRES_IN = "expiresIn";

var parkMap = {
    acad: 'Acadia National Park',
    arch: 'Arches National Park',
    badl: 'Badlands National Park',
    brca: 'Bryce Canyon National Park',
    crla: 'Crater Lake National Park',
    dena: 'Denali National Park',
    glac: 'Glacier National Park',
    grca: 'Grand Canyon National Park',
    grte: 'Grand Teton National Park',
    olym: 'Olympic National Park',
    yell: 'Yellowstone National Park',
    yose: 'Yosemite National Park',
    zion: 'Zion National Park'
};

var getBadges = function (t) {
    return t.card('name')
        .get('name')
        .then(function (cardName) {
            var badgeColor;
            var icon = GRAY_ICON;
            var lowercaseName = cardName.toLowerCase();
            if (lowercaseName.indexOf('green') > -1) {
                badgeColor = 'green';
                icon = WHITE_ICON;
            } else if (lowercaseName.indexOf('yellow') > -1) {
                badgeColor = 'yellow';
                icon = WHITE_ICON;
            } else if (lowercaseName.indexOf('red') > -1) {
                badgeColor = 'red';
                icon = WHITE_ICON;
            }

            if (lowercaseName.indexOf('dynamic') > -1) {
                // dynamic badges can have their function rerun after a set number
                // of seconds defined by refresh. Minimum of 10 seconds.
                return [{
                    dynamic: function () {
                        return {
                            title: 'Detail Badge', // for detail badges only
                            text: 'Dynamic ' + (Math.random() * 100).toFixed(0).toString(),
                            icon: icon, // for card front badges only
                            color: badgeColor,
                            refresh: 10
                        }
                    }
                }]
            }

            if (lowercaseName.indexOf('static') > -1) {
                // return an array of badge objects
                return [{
                    title: 'Detail Badge', // for detail badges only
                    text: 'Static',
                    icon: icon, // for card front badges only
                    color: badgeColor
                }];
            } else {
                return [];
            }
        })
};

var formatNPSUrl = function (t, url) {
    if (!/^https?:\/\/www\.nps\.gov\/[a-z]{4}\//.test(url)) {
        return null;
    }
    var parkShort = /^https?:\/\/www\.nps\.gov\/([a-z]{4})\//.exec(url)[1];
    if (parkShort && parkMap[parkShort]) {
        return parkMap[parkShort];
    } else {
        return null;
    }
};

var boardButtonCallback = function (t) {
    /*return t.popup({
        title: 'Popup List Example',
        items: [
            {
                text: 'Open Overlay',
                callback: function (t) {
                    return t.overlay({
                        url: './overlay.html',
                        args: {rand: (Math.random() * 100).toFixed(0)}
                    })
                        .then(function () {
                            return t.closePopup();
                        });
                }
            },
            {
                text: 'Open Board Bar',
                callback: function (t) {
                    return t.boardBar({
                        url: './board-bar.html',
                        height: 200
                    })
                        .then(function () {
                            return t.closePopup();
                        });
                }
            }
        ]
    });*/

    return t.overlay({
        url: './javascript/editor/grapheditor/www/index.html',
        args: {rand: (Math.random() * 100).toFixed(0)}
    })
        .then(function () {
            return t.closePopup();
        });

};

var cardButtonCallback = function (t) {
    /*var items = Object.keys(parkMap).map(function (parkCode) {
        var urlForCode = 'http://www.nps.gov/' + parkCode + '/';
        return {
            text: parkMap[parkCode],
            url: urlForCode,
            callback: function (t) {
                return t.attach({url: urlForCode, name: parkMap[parkCode]})
                    .then(function () {
                        return t.closePopup();
                    })
            }
        };
    });

    return t.popup({
        title: 'Popup Search Example',
        items: items,
        search: {
            count: 5,
            placeholder: 'Search National Parks',
            empty: 'No parks found'
        }
    });*/

    return t.overlay({
        url: '../index.html',
        args: {rand: (Math.random() * 100).toFixed(0)}
    })
        .then(function () {
            return t.closePopup();
        });

};

TrelloPowerUp.initialize({

    'authorization-status': function(t) {

        /*return t.get('board', 'private', KEY_ACCESS_TOKEN, DEFAULT)
            .then(function (token) {
                console.log(token);

                if(token===DEFAULT) {

                    // if false
                    // `show-authorization` is displayed
                    return new TrelloPowerUp.Promise((resolve) =>
                        resolve({ authorized: false })
                    )
                }
                else {

                    // if true
                    // t.set has been used
                    // `remove settings` is displayed

                    return new TrelloPowerUp.Promise((resolve) =>
                        resolve({ authorized: true })
                    )

                }

            });*/

        return new TrelloPowerUp.Promise((resolve) =>
            resolve({ authorized: true })
        )

    },

    'show-authorization': function(t) {
        return t.popup({
            title: 'Authorize',
            items: [
                {
                    text: "Connect Microsoft or Office 365 Account",
                    callback: function () {
                        console.log("TODO settings auth");
                    }
                }
            ]
        });
    },

    'show-settings': function (t, options) {
        return t.popup({
            title: 'Settings',
            url: './settings.html',
            height: 184
        });
    },

    // Allows you to add one or more buttons on the right side of the back of cards
    // Each button should have { icon, text, callback -> method }
    'card-buttons': function (t, options) {
        return [{
            icon: GRAY_ICON,
            text: 'New Drawing',
            callback: cardButtonCallback
        }];
    },

    'attachment-sections': function (t, options) {

        //console.log(JSON.stringify(options));

        // options.entries is a list of the attachments for this card
        // you can look through them and 'claim' any that you want to
        // include in your section.

        // we will just claim urls for Yellowstone
        var claimed = options.entries.filter(drawFilter);

        // you can have more than one attachment section on a card
        // you can group items together into one section, have a section
        // per attachment, or anything in between.
        if (claimed && claimed.length > 0) {
            // if the title for your section requires a network call or other
            // potentially length operation you can provide a function for the title
            // that returns the section title. If you do so, provide a unique id for
            // your section

            //console.log(JSON.stringify(claimed));

            return [{
                id: BASE_URL, // optional if you aren't using a function for the title
                claimed: claimed,
                icon: GRAY_ICON,
                title: 'Attached Drawings',
                content: {
                    type: 'iframe',
                    url: t.signUrl('./section.html', {arg: claimed}),
                    height: 230
                }
            }];
        } else {
            return [];
        }
    },
    'attachment-thumbnail': function (t, attachment) {
        var name = formatDrawUrl(t, attachment.url);
        if (name) {
            // return an object with some or all of these properties:
            // url, title, image, openText, modified (Date), created (Date), createdBy, modifiedBy
            return {
                title: name,
                url: attachment.url,
                openText: "Open Externally",
                image: {
                    url: './images/icon-gray.svg',
                    logo: true // false if this is a thumbnail
                },
                initialize: {
                    type: 'iframe',
                    url: TrelloPowerUp.util.relativeUrl('./authorize.html')
                }
            };
        } else {
            throw t.NotHandled();
        }
    },

    // Allows you to add one or more buttons to a Board at the top right of the screen
    'board-buttons': function (t, options) {
        return [{
            icon: WHITE_ICON,
            text: 'Office 365',
            callback: boardButtonCallback
        }];
    },

    'card-badges': function (t, card) {
        console.log('card-badges');
        //console.log(JSON.stringify(t));
        //console.log(JSON.stringify(card));
        return getBadges(t);
    },

    'card-detail-badges': function (t, options) {
        return getBadges(t);
    },
    'card-from-url': function (t, options) {
        var parkName = formatNPSUrl(t, options.url);
        if (parkName) {
            return {
                name: parkName,
                desc: 'An awesome park: ' + options.url
            };
        } else {
            throw t.NotHandled();
        }
    },
    'format-url': function (t, options) {
        var name = formatDrawUrl(t, options.url);

        console.log("format-url> "+JSON.stringify(name));

        if (name) {
            return {
                icon: GRAY_ICON,
                text: name
            };
        } else {
            throw t.NotHandled();
        }
    }
});
<commit_msg>card badge<commit_after>/* global TrelloPowerUp */

var WHITE_ICON = './images/icon-white.svg';
var GRAY_ICON = './images/icon-gray.svg';
var APP_ID = '380ed9c5-4e06-4b73-b2e0-115ab3810cb8';
var DEFAULT = "XXX";

var KEY_ACCESS_TOKEN = "accessToken";
var KEY_ENDPOINT_HINT= "endpointHint";
var KEY_REFRESH_TOKEN = "refreshToken";
var KEY_EXPIRES_IN = "expiresIn";

var parkMap = {
    acad: 'Acadia National Park',
    arch: 'Arches National Park',
    badl: 'Badlands National Park',
    brca: 'Bryce Canyon National Park',
    crla: 'Crater Lake National Park',
    dena: 'Denali National Park',
    glac: 'Glacier National Park',
    grca: 'Grand Canyon National Park',
    grte: 'Grand Teton National Park',
    olym: 'Olympic National Park',
    yell: 'Yellowstone National Park',
    yose: 'Yosemite National Park',
    zion: 'Zion National Park'
};

var getBadges = function (t) {
    return t.card('attachments')
        .get('attachments')
        .then(function (attachments) {

            var cnt = 0;

            var len = attachments.length;
            for (var i = 0; i < len; i++) {
                var name = formatDrawUrl(null, attachments[i].url);
                if (name) {
                    cnt++;
                }
            }

            if (cnt > 0) {
                var badgeColor = 'orange';
                var icon = WHITE_ICON;
                var text = (cnt == 1) ? "1 Drawing" : cnt + " Drawings";

                // return an array of badge objects
                return [{
                    text: text,
                    icon: icon, // for card front badges only
                    color: badgeColor
                }];
            } else {
                return [];
            }
        });
};

var formatNPSUrl = function (t, url) {
    if (!/^https?:\/\/www\.nps\.gov\/[a-z]{4}\//.test(url)) {
        return null;
    }
    var parkShort = /^https?:\/\/www\.nps\.gov\/([a-z]{4})\//.exec(url)[1];
    if (parkShort && parkMap[parkShort]) {
        return parkMap[parkShort];
    } else {
        return null;
    }
};

var boardButtonCallback = function (t) {
    /*return t.popup({
        title: 'Popup List Example',
        items: [
            {
                text: 'Open Overlay',
                callback: function (t) {
                    return t.overlay({
                        url: './overlay.html',
                        args: {rand: (Math.random() * 100).toFixed(0)}
                    })
                        .then(function () {
                            return t.closePopup();
                        });
                }
            },
            {
                text: 'Open Board Bar',
                callback: function (t) {
                    return t.boardBar({
                        url: './board-bar.html',
                        height: 200
                    })
                        .then(function () {
                            return t.closePopup();
                        });
                }
            }
        ]
    });*/

    return t.overlay({
        url: './javascript/editor/grapheditor/www/index.html',
        args: {rand: (Math.random() * 100).toFixed(0)}
    })
        .then(function () {
            return t.closePopup();
        });

};

var cardButtonCallback = function (t) {
    /*var items = Object.keys(parkMap).map(function (parkCode) {
        var urlForCode = 'http://www.nps.gov/' + parkCode + '/';
        return {
            text: parkMap[parkCode],
            url: urlForCode,
            callback: function (t) {
                return t.attach({url: urlForCode, name: parkMap[parkCode]})
                    .then(function () {
                        return t.closePopup();
                    })
            }
        };
    });

    return t.popup({
        title: 'Popup Search Example',
        items: items,
        search: {
            count: 5,
            placeholder: 'Search National Parks',
            empty: 'No parks found'
        }
    });*/

    return t.overlay({
        url: '../index.html',
        args: {rand: (Math.random() * 100).toFixed(0)}
    })
        .then(function () {
            return t.closePopup();
        });

};

TrelloPowerUp.initialize({

    'authorization-status': function(t) {

        /*return t.get('board', 'private', KEY_ACCESS_TOKEN, DEFAULT)
            .then(function (token) {
                console.log(token);

                if(token===DEFAULT) {

                    // if false
                    // `show-authorization` is displayed
                    return new TrelloPowerUp.Promise((resolve) =>
                        resolve({ authorized: false })
                    )
                }
                else {

                    // if true
                    // t.set has been used
                    // `remove settings` is displayed

                    return new TrelloPowerUp.Promise((resolve) =>
                        resolve({ authorized: true })
                    )

                }

            });*/

        return new TrelloPowerUp.Promise((resolve) =>
            resolve({ authorized: true })
        )

    },

    'show-authorization': function(t) {
        return t.popup({
            title: 'Authorize',
            items: [
                {
                    text: "Connect Microsoft or Office 365 Account",
                    callback: function () {
                        console.log("TODO settings auth");
                    }
                }
            ]
        });
    },

    'show-settings': function (t, options) {
        return t.popup({
            title: 'Settings',
            url: './settings.html',
            height: 184
        });
    },

    // Allows you to add one or more buttons on the right side of the back of cards
    // Each button should have { icon, text, callback -> method }
    'card-buttons': function (t, options) {
        return [{
            icon: GRAY_ICON,
            text: 'New Drawing',
            callback: cardButtonCallback
        }];
    },

    'attachment-sections': function (t, options) {

        //console.log(JSON.stringify(options));

        // options.entries is a list of the attachments for this card
        // you can look through them and 'claim' any that you want to
        // include in your section.

        // we will just claim urls for Yellowstone
        var claimed = options.entries.filter(drawFilter);

        // you can have more than one attachment section on a card
        // you can group items together into one section, have a section
        // per attachment, or anything in between.
        if (claimed && claimed.length > 0) {
            // if the title for your section requires a network call or other
            // potentially length operation you can provide a function for the title
            // that returns the section title. If you do so, provide a unique id for
            // your section

            //console.log(JSON.stringify(claimed));

            return [{
                id: BASE_URL, // optional if you aren't using a function for the title
                claimed: claimed,
                icon: GRAY_ICON,
                title: 'Attached Drawings',
                content: {
                    type: 'iframe',
                    url: t.signUrl('./section.html', {arg: claimed}),
                    height: 230
                }
            }];
        } else {
            return [];
        }
    },
    'attachment-thumbnail': function (t, attachment) {
        var name = formatDrawUrl(t, attachment.url);
        if (name) {
            // return an object with some or all of these properties:
            // url, title, image, openText, modified (Date), created (Date), createdBy, modifiedBy
            return {
                title: name,
                url: attachment.url,
                openText: "Open Externally",
                image: {
                    url: './images/icon-gray.svg',
                    logo: true // false if this is a thumbnail
                },
                initialize: {
                    type: 'iframe',
                    url: TrelloPowerUp.util.relativeUrl('./authorize.html')
                }
            };
        } else {
            throw t.NotHandled();
        }
    },

    // Allows you to add one or more buttons to a Board at the top right of the screen
    'board-buttons': function (t, options) {
        return [{
            icon: WHITE_ICON,
            text: 'Office 365',
            callback: boardButtonCallback
        }];
    },

    'card-badges': function (t, card) {
        console.log('card-badges');
        //console.log(JSON.stringify(t));
        //console.log(JSON.stringify(card));
        return getBadges(t);
    },

    'card-detail-badges': function (t, options) {
        return getBadges(t);
    },
    'card-from-url': function (t, options) {
        var parkName = formatNPSUrl(t, options.url);
        if (parkName) {
            return {
                name: parkName,
                desc: 'An awesome park: ' + options.url
            };
        } else {
            throw t.NotHandled();
        }
    },
    'format-url': function (t, options) {
        var name = formatDrawUrl(t, options.url);

        console.log("format-url> "+JSON.stringify(name));

        if (name) {
            return {
                icon: GRAY_ICON,
                text: name
            };
        } else {
            throw t.NotHandled();
        }
    }
});
<|endoftext|>


<commit_before>module.exports = {
	useTabs: true,
	tabWidth: 4,
	printWidth: 80,
	singleQuote: true,
	trailingComma: 'es5',
	bracketSpacing: true,
	parenSpacing: true,
	jsxBracketSameLine: false,
	semi: true,
	arrowParens: 'always',
};
<commit_msg>chore: add `endOfLine` Prettier option `lf`<commit_after>module.exports = {
	useTabs: true,
	tabWidth: 4,
	printWidth: 80,
	singleQuote: true,
	trailingComma: 'es5',
	bracketSpacing: true,
	parenSpacing: true,
	jsxBracketSameLine: false,
	semi: true,
	arrowParens: 'always',
	endOfLine: 'lf',
};
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Wed Dec 24 2014 19:30:10 GMT-0200 (Horário brasileiro de verão)

var _karma = function(config)
{
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'bower_components/angular/angular.js',

      'bower_components/angular-mocks/angular-mocks.js',

      'src/**/*.js',

      'tests/*_test.js'
    ],

    // list of files to exclude
    exclude: [],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'src/<%= app %>.js': 'coverage'
    },

    coverageReporter:
    {
      type: 'lcov',
      dir: 'coverage'
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS', 'Chrome', 'IE', 'Safari', 'Firefox', 'FirefoxNightly', 'ChromeCanary'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  });
};

module.exports = _karma;
<commit_msg>Ajusta configuração de coverage<commit_after>// Karma configuration
// Generated on Wed Dec 24 2014 19:30:10 GMT-0200 (Horário brasileiro de verão)

var _karma = function(config)
{
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'bower_components/angular/angular.js',

      'bower_components/angular-mocks/angular-mocks.js',

      'src/**/*.js',

      'tests/*_test.js'
    ],

    // list of files to exclude
    exclude: [],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'src/**/*.js': 'coverage'
    },

    coverageReporter:
    {
      type: 'lcov',
      dir: 'coverage'
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS', 'Chrome', 'IE', 'Safari', 'Firefox', 'FirefoxNightly', 'ChromeCanary'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  });
};

module.exports = _karma;
<|endoftext|>


<commit_before>/* eslint-disable */
var path = require('path');
var args = require('yargs').argv;

// var specFileFilter = 'source/test/unit-test.index.js';
var specFileFilter = 'source/app/**/*.spec.js';
var singleRun = !args.watch;
var browser = args.watch ? 'PhantomJS' : 'Chrome';

var include = [
    path.resolve('./source/app')
];
// only use coverage/junit in non-watch mode
var preLoaders = !args.watch ? [
    // Process test code with Babel
    {test: /\.spec\.js$/, loader: 'babel', include: include},
    // Process all non-test code with Isparta
    {test: /\.js$/, loader: 'isparta', include: include, exclude: /\.spec\.js$/}
] : [
    {test: /\.js$/, loader: 'babel', include: include}
];
var reporters = args.watch ? [
    'mocha'
] : [
    'mocha', 'coverage', 'junit'
];

var loaders = [
    {test: /\.styl$/, loader: 'style!css!stylus'},
    {test: /\.jade$/, loader: 'jade'},
    {test: /\.(png|jpg)$/, loader: 'null'}
];
var processors = {};
processors[specFileFilter] = ['webpack'];

module.exports = function (config) {
    config.set({
        basePath: '.',
        frameworks: ['jasmine'],
        exclude: [],
        files: [
            specFileFilter
        ],
        webpack: {
            devtool: 'eval',
            module: {
                preLoaders: preLoaders,
                loaders: loaders
            },
            cache: true
        },
        webpackMiddleware: {
            stats: {
                chunkModules: false,
                colors: true
            }
        },
        preprocessors: processors,
        reporters: reporters,
        coverageReporter: {
            dir: 'source/test/unit/results/coverage',
            reporters: [
                {type: 'html', subdir: '.'},
                {type: 'text-summary'}
            ]
        },
        junitReporter: {
            outputDir: 'source/test/unit/results/junit'
        },
        reportSlowerThan: 500,
        singleRun: singleRun,
        browsers: [
            browser
        ]
    });
};
<commit_msg>use karma-sourcemap-loader<commit_after>/* eslint-disable */
var path = require('path');
var args = require('yargs').argv;

// var specFileFilter = 'source/test/unit-test.index.js';
var specFileFilter = 'source/app/**/*.spec.js';
var singleRun = !args.watch;
var browser = args.watch ? 'PhantomJS' : 'Chrome';

var include = [
    path.resolve('./source/app')
];
// only use coverage/junit in non-watch mode
var preLoaders = !args.watch ? [
    // Process test code with Babel
    {test: /\.spec\.js$/, loader: 'babel', include: include},
    // Process all non-test code with Isparta
    {test: /\.js$/, loader: 'isparta', include: include, exclude: /\.spec\.js$/}
] : [
    {test: /\.js$/, loader: 'babel', include: include}
];
var reporters = args.watch ? [
    'mocha'
] : [
    'mocha', 'coverage', 'junit'
];

var loaders = [
    {test: /\.styl$/, loader: 'style!css!stylus'},
    {test: /\.jade$/, loader: 'jade'},
    {test: /\.(png|jpg)$/, loader: 'null'}
];
var processors = {};
processors[specFileFilter] = ['webpack', 'sourcemap'];

module.exports = function (config) {
    config.set({
        basePath: '.',
        frameworks: ['jasmine'],
        exclude: [],
        files: [
            specFileFilter
        ],
        webpack: {
            devtool: 'inline-source-map',
            module: {
                preLoaders: preLoaders,
                loaders: loaders
            },
            cache: true
        },
        webpackMiddleware: {
            stats: {
                chunkModules: false,
                colors: true
            }
        },
        preprocessors: processors,
        reporters: reporters,
        coverageReporter: {
            dir: 'source/test/unit/results/coverage',
            reporters: [
                {type: 'html', subdir: '.'},
                {type: 'text-summary'}
            ]
        },
        junitReporter: {
            outputDir: 'source/test/unit/results/junit'
        },
        reportSlowerThan: 500,
        singleRun: singleRun,
        browsers: [
            browser
        ]
    });
};
<|endoftext|>


<commit_before>var expect = require("chai").expect;

var copyrightHelper = require('../helpers/modules/copyright');

describe('copyright', function() {

    'use strict';

    describe('Arguments validation', function() {

        it('should throw TypeError if startYear argument is not an integer', function() {
            var err = new TypeError('startYear must be an integer');
            expect(copyrightHelper.getCopyright.bind('2019', 2023)).to.throw(TypeError);
        });

        it('should throw TypeError if currentYear argument is not an integer', function() {
            var err = new TypeError('currentYear must be an integer');
            expect(copyrightHelper.getCopyright.bind(2017, '2019')).to.throw(TypeError);
        });

        it('should throw RangeError if currentYear argument is less than startYear', function() {
            var err = new TypeError('startYear must be equal to or less than currentYear');
            expect(copyrightHelper.getCopyright.bind(2020, 2028)).to.throw(TypeError);
        });

    });

    describe('Return values', function() {

        it('should return correct text if startYear is equal to currentYear', function() {
            var startYear = 2018,
                currentYear = 2018,
                text = `${currentYear}`;

            var copyright = copyrightHelper.getCopyright(startYear, currentYear);

            expect(copyright).to.equal(text);
        });

        it('should return correct text if startYear is less than currentYear', function() {
            var startYear = 2014,
                currentYear = 2020,
                text = `${startYear} - ${currentYear}`;

            var copyright = copyrightHelper.getCopyright(startYear, currentYear);

            expect(copyright).to.equal(text);
        });

    });

});<commit_msg>Fix copyright module tests<commit_after>var expect = require("chai").expect;

var copyrightHelper = require('../helpers/modules/copyright');

describe('copyright', function() {

    'use strict';

    describe('Arguments validation', function() {

        it('should throw TypeError if startYear argument is not an integer', function() {
            var fn = function(){
                copyrightHelper.getCopyright('2019', 2023);
            };

            expect(fn).to.throw(TypeError, 'startYear must be an integer');
        });

        it('should throw TypeError if currentYear argument is not an integer', function() {
            var fn = function(){
                copyrightHelper.getCopyright(2017, '2019');
            };

            expect(fn).to.throw(TypeError, 'currentYear must be an integer');
        });

        it('should throw RangeError if currentYear argument is less than startYear', function() {
            var fn = function(){
                copyrightHelper.getCopyright(2028, 2020);
            };

            expect(fn).to.throw(RangeError, 'startYear must be equal to or less than currentYear');

        });

    });

    describe('Return values', function() {

        it('should return correct text if startYear is equal to currentYear', function() {
            var startYear = 2018,
                currentYear = 2018,
                text = `${currentYear}`;

            var copyright = copyrightHelper.getCopyright(startYear, currentYear);

            expect(copyright).to.equal(text);
        });

        it('should return correct text if startYear is less than currentYear', function() {
            var startYear = 2014,
                currentYear = 2020,
                text = `${startYear} - ${currentYear}`;

            var copyright = copyrightHelper.getCopyright(startYear, currentYear);

            expect(copyright).to.equal(text);
        });

    });

});<|endoftext|>