<commit_before>// ***********************************************//
//                 Router
// ***********************************************//
require('akvo-flow/core-common');

FLOW.Router = Ember.Router.extend({
  enableLogging: true,
  loggedIn: false,
  location: 'none',
  //'hash'or 'none' for URLs

  resetState: function () {
    // We could have unsaved changes
    FLOW.store.commit();

    FLOW.selectedControl.set('selectedQuestionGroup', null);
    FLOW.selectedControl.set('selectedSurveyGroup', null);
    FLOW.selectedControl.set('selectedSurvey', null);
    FLOW.selectedControl.set('selectedQuestion', null);
    FLOW.selectedControl.set('selectedCascadeResource', null);
    FLOW.selectedControl.set('cascadeImportNumLevels', null);
    FLOW.selectedControl.set('cascadeImportIncludeCodes', null);
    FLOW.surveyControl.set('content', null);
    FLOW.questionControl.set('OPTIONcontent', null);
    FLOW.metaControl.set('since', null);
  },

  root: Ember.Route.extend({
    doNavSurveys: function (router, context) {
      router.transitionTo('navSurveys.index');
    },
    doNavDevices: function (router, context) {
      router.transitionTo('navDevices.index');
    },
    doNavData: function (router, context) {
      router.transitionTo('navData.index');
    },
    doNavReports: function (router, context) {
      router.transitionTo('navReports.index');
    },
    doNavMaps: function (router, context) {
      router.transitionTo('navMaps');
    },
    doNavUsers: function (router, context) {
      router.transitionTo('navUsers');
    },
    doNavMessages: function (router, context) {
      router.transitionTo('navMessages');
    },
    // not used at the moment
    doNavAdmin: function (router, context) {
      router.transitionTo('navAdmin');
    },

    // non-working code for transitioning to navHome at first entry of the app
    //    setup: function(router){
    //      router.send("goHome");
    //    },
    //    goHome:function(router){
    //      router.transitionTo('navHome');
    //    },
    index: Ember.Route.extend({
      route: '/',
      redirectsTo: 'navSurveys.index'
    }),

    // ******************* SURVEYS ROUTER ********************
    navSurveys: Ember.Route.extend({
      route: '/surveys',
      connectOutlets: function (router, event) {
        router.get('applicationController').connectOutlet('navSurveys');
        router.set('navigationController.selected', 'navSurveys');
        FLOW.cascadeResourceControl.populate();
      },

      doNewSurvey: function (router, event) {
        router.transitionTo('navSurveys.navSurveysNew');
      },

      doEditSurvey: function (router, event) {
        FLOW.selectedControl.set('selectedSurvey', event.context);
        router.transitionTo('navSurveys.navSurveysEdit.index');
      },

      doSurveysMain: function (router, event) {
        FLOW.selectedControl.set('selectedQuestion', null);
        router.transitionTo('navSurveys.navSurveysMain');
      },

      index: Ember.Route.extend({
        route: '/',
        redirectsTo: 'navSurveysMain'
      }),

      navSurveysMain: Ember.Route.extend({
        route: '/main',
        connectOutlets: function (router, event) {
          router.get('navSurveysController').connectOutlet({
            name: 'navSurveysMain'
          });
          FLOW.projectControl.populate();
          FLOW.projectControl.set('currentProject', null);
          FLOW.projectControl.set('newlyCreated', null);
          FLOW.selectedControl.set('selectedQuestionGroup', null);
          FLOW.selectedControl.set('selectedSurvey', null);
          FLOW.selectedControl.set('selectedQuestion', null);
          FLOW.questionControl.set('OPTIONcontent', null);
          FLOW.attributeControl.populate();

        }
      }),

      navSurveysNew: Ember.Route.extend({
        route: '/new',
        connectOutlets: function (router, event) {
          var newSurvey;

          newSurvey = FLOW.store.createRecord(FLOW.Survey, {
            "name": "",
            "defaultLanguageCode": "en",
            "requireApproval": false,
            "status": "NOT_PUBLISHED",
            "surveyGroupId": FLOW.selectedControl.selectedSurveyGroup.get('keyId'),
            "version":"1.0"
          });

          FLOW.selectedControl.set('selectedSurvey', newSurvey);
          router.transitionTo('navSurveys.navSurveysEdit.index');
        }
      }),

      navSurveysEdit: Ember.Route.extend({
        route: '/edit',
        connectOutlets: function (router, event) {
          router.get('navSurveysController').connectOutlet({
            name: 'navSurveysEdit'
          });
          // all questions should be closed when we enter
          FLOW.selectedControl.set('selectedQuestion', null);
          FLOW.attributeControl.populate();
        },

        doEditQuestions: function (router, event) {
          router.transitionTo('navSurveys.navSurveysEdit.editQuestions');
        },

        index: Ember.Route.extend({
          route: '/',
          redirectsTo: 'editQuestions'
        }),

        manageNotifications: Ember.Route.extend({
          route: '/notifications',
          connectOutlets: function (router, event) {
            router.get('navSurveysEditController').connectOutlet({
              name: 'manageNotifications'
            });
            FLOW.notificationControl.populate();
          }
        }),

        manageTranslations: Ember.Route.extend({
          route: '/translations',
          connectOutlets: function (router, event) {
            router.get('navSurveysEditController').connectOutlet({
              name: 'manageTranslations'
            });
            FLOW.translationControl.populate();
          }
        }),

        editQuestions: Ember.Route.extend({
          route: '/questions',
          connectOutlets: function (router, event) {
            router.get('navSurveysEditController').connectOutlet({
              name: 'editQuestions'
            });

          }
        })
      })
    }),

    //********************** DEVICES ROUTER *******************
    navDevices: Ember.Route.extend({
      route: '/devices',
      connectOutlets: function (router, event) {
        router.get('applicationController').connectOutlet('navDevices');
        router.set('navigationController.selected', 'navDevices');
      },

      doCurrentDevices: function (router, event) {
        router.transitionTo('navDevices.currentDevices');
      },

      doAssignSurveysOverview: function (router, event) {
        router.transitionTo('navDevices.assignSurveysOverview');
      },

      doEditSurveysAssignment: function (router, event) {
        router.transitionTo('navDevices.editSurveysAssignment');
      },

      doSurveyBootstrap: function (router, event) {
        router.transitionTo('navDevices.surveyBootstrap');
      },

      index: Ember.Route.extend({
        route: '/',
        redirectsTo: 'currentDevices'
      }),

      currentDevices: Ember.Route.extend({
        route: '/current-devices',
        connectOutlets: function (router, context) {
          router.get('navDevicesController').connectOutlet('currentDevices');
          router.resetState();
          FLOW.deviceGroupControl.populate();
          FLOW.deviceControl.populate();
          FLOW.surveyAssignmentControl.populate();
          FLOW.surveyGroupControl.populate();
          router.set('devicesSubnavController.selected', 'currentDevices');
        }
      }),

      assignSurveysOverview: Ember.Route.extend({
        route: '/assign-surveys',
        connectOutlets: function (router, context) {
          router.get('navDevicesController').connectOutlet('assignSurveysOverview');
          router.set('devicesSubnavController.selected', 'assignSurveys');
        }
      }),

      editSurveysAssignment: Ember.Route.extend({
        route: '/assign-surveys',
        connectOutlets: function (router, context) {
          router.get('navDevicesController').connectOutlet('editSurveyAssignment');
          router.set('devicesSubnavController.selected', 'assignSurveys');
        }
      }),

      surveyBootstrap: Ember.Route.extend({
        route: '/manual-transfer',
        connectOutlets: function (router, context) {
          router.get('navDevicesController').connectOutlet('surveyBootstrap');
          router.set('devicesSubnavController.selected', 'surveyBootstrap');
        }
      })
    }),

    // ******************* DATA ROUTER ***********************
    navData: Ember.Route.extend({
      route: '/data',
      connectOutlets: function (router, event) {
        router.get('applicationController').connectOutlet('navData');
        router.set('navigationController.selected', 'navData');
      },

      doInspectData: function (router, event) {
        router.transitionTo('navData.inspectData');
      },
      doManageAttributes: function (router, event) {
        router.transitionTo('navData.manageAttributes');
      },
      doBulkUpload: function (router, event) {
        router.transitionTo('navData.bulkUpload');
      },
      doDataCleaning: function (router, event) {
        router.transitionTo('navData.dataCleaning');
      },
      doCascadeResources: function (router, event) {
          router.transitionTo('navData.cascadeResources');
        },
      doMonitoringData: function (router, event) {
        router.transitionTo('navData.monitoringData');
      },

      index: Ember.Route.extend({
        route: '/',
        redirectsTo: 'inspectData'
      }),

      inspectData: Ember.Route.extend({
        route: '/inspectdata',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('inspectData');
          router.set('datasubnavController.selected', 'inspectData');
          router.resetState();
        }
      }),

      manageAttributes: Ember.Route.extend({
        route: '/manageattributes',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('manageAttributes');
          router.set('datasubnavController.selected', 'manageAttributes');
          FLOW.attributeControl.populate();
        }
      }),

      bulkUpload: Ember.Route.extend({
        route: '/bulkupload',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('bulkUpload');
          router.set('datasubnavController.selected', 'bulkUpload');
        }
      }),

      dataCleaning: Ember.Route.extend({
        route: '/datacleaning',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('dataCleaning');
          router.set('datasubnavController.selected', 'dataCleaning');
          router.resetState();
        }
      }),

      cascadeResources: Ember.Route.extend({
          route: '/cascaderesources',
          connectOutlets: function (router, context) {
            router.get('navDataController').connectOutlet('cascadeResources');
            router.set('datasubnavController.selected', 'cascadeResources');
            FLOW.cascadeResourceControl.populate();
          }
        }),

      monitoringData: Ember.Route.extend({
        route: '/monitoringdata',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('monitoringData');
          router.set('datasubnavController.selected', 'monitoringData');
          router.resetState();
          FLOW.surveyGroupControl.populate(function (item) {
                 return item.get('monitoringGroup');
          });
        }
      }),
    }),

    // ************************** REPORTS ROUTER **********************************
    navReports: Ember.Route.extend({
      route: '/reports',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navReports');
        router.resetState();
        router.set('navigationController.selected', 'navReports');
      },

      doExportReports: function (router, event) {
        router.transitionTo('navReports.exportReports');
      },

      doChartReports: function (router, event) {
        router.transitionTo('navReports.chartReports');
      },

      doStatistics: function(router, event) {
        router.transitionTo('navReports.statistics');
      },

      index: Ember.Route.extend({
        route: '/',
        redirectsTo: 'chartReports'
      }),

      exportReports: Ember.Route.extend({
        route: '/exportreports',
        connectOutlets: function (router, context) {
          router.get('navReportsController').connectOutlet('exportReports');
          router.set('reportsSubnavController.selected', 'exportReports');
          router.resetState();
        }
      }),

      chartReports: Ember.Route.extend({
        route: '/chartreports',
        connectOutlets: function (router, context) {
          router.resetState();
          router.get('navReportsController').connectOutlet('chartReports');
          router.set('reportsSubnavController.selected', 'chartReports');
        }
      }),
      statistics: Ember.Route.extend({
        route: '/statistics',
        connectOutlets: function(router, context) {
          router.resetState();
          router.get('navReportsController').connectOutlet('statistics');
          router.set('reportsSubnavController.selected', 'statistics');
          FLOW.surveyGroupControl.populate();
        }
      })
    }),

    // ************************** MAPS ROUTER **********************************
    navMaps: Ember.Route.extend({
      route: '/maps',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navMaps');
        router.set('navigationController.selected', 'navMaps');
      }
    }),

    // ************************** USERS ROUTER **********************************
    navUsers: Ember.Route.extend({
      route: '/users',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navUsers');
        router.set('navigationController.selected', 'navUsers');
        FLOW.userControl.populate();
      }
    }),

    // ************************** MESSAGES ROUTER **********************************
    navMessages: Ember.Route.extend({
      route: '/users',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navMessages');
        router.set('navigationController.selected', 'navMessages');
        FLOW.messageControl.populate();
        router.resetState();
      }
    }),

    // ************************** ADMIN ROUTER **********************************
    // not used at the moment
    navAdmin: Ember.Route.extend({
      route: '/admin',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navAdmin');
        router.set('navigationController.selected', 'navAdmin');
      }
    })
  })
});
<commit_msg>[#1053] Don't fetch survey groups in monitoring tab<commit_after>// ***********************************************//
//                 Router
// ***********************************************//
require('akvo-flow/core-common');

FLOW.Router = Ember.Router.extend({
  enableLogging: true,
  loggedIn: false,
  location: 'none',
  //'hash'or 'none' for URLs

  resetState: function () {
    // We could have unsaved changes
    FLOW.store.commit();

    FLOW.selectedControl.set('selectedQuestionGroup', null);
    FLOW.selectedControl.set('selectedSurveyGroup', null);
    FLOW.selectedControl.set('selectedSurvey', null);
    FLOW.selectedControl.set('selectedQuestion', null);
    FLOW.selectedControl.set('selectedCascadeResource', null);
    FLOW.selectedControl.set('cascadeImportNumLevels', null);
    FLOW.selectedControl.set('cascadeImportIncludeCodes', null);
    FLOW.surveyControl.set('content', null);
    FLOW.questionControl.set('OPTIONcontent', null);
    FLOW.metaControl.set('since', null);
  },

  root: Ember.Route.extend({
    doNavSurveys: function (router, context) {
      router.transitionTo('navSurveys.index');
    },
    doNavDevices: function (router, context) {
      router.transitionTo('navDevices.index');
    },
    doNavData: function (router, context) {
      router.transitionTo('navData.index');
    },
    doNavReports: function (router, context) {
      router.transitionTo('navReports.index');
    },
    doNavMaps: function (router, context) {
      router.transitionTo('navMaps');
    },
    doNavUsers: function (router, context) {
      router.transitionTo('navUsers');
    },
    doNavMessages: function (router, context) {
      router.transitionTo('navMessages');
    },
    // not used at the moment
    doNavAdmin: function (router, context) {
      router.transitionTo('navAdmin');
    },

    // non-working code for transitioning to navHome at first entry of the app
    //    setup: function(router){
    //      router.send("goHome");
    //    },
    //    goHome:function(router){
    //      router.transitionTo('navHome');
    //    },
    index: Ember.Route.extend({
      route: '/',
      redirectsTo: 'navSurveys.index'
    }),

    // ******************* SURVEYS ROUTER ********************
    navSurveys: Ember.Route.extend({
      route: '/surveys',
      connectOutlets: function (router, event) {
        router.get('applicationController').connectOutlet('navSurveys');
        router.set('navigationController.selected', 'navSurveys');
        FLOW.cascadeResourceControl.populate();
      },

      doNewSurvey: function (router, event) {
        router.transitionTo('navSurveys.navSurveysNew');
      },

      doEditSurvey: function (router, event) {
        FLOW.selectedControl.set('selectedSurvey', event.context);
        router.transitionTo('navSurveys.navSurveysEdit.index');
      },

      doSurveysMain: function (router, event) {
        FLOW.selectedControl.set('selectedQuestion', null);
        router.transitionTo('navSurveys.navSurveysMain');
      },

      index: Ember.Route.extend({
        route: '/',
        redirectsTo: 'navSurveysMain'
      }),

      navSurveysMain: Ember.Route.extend({
        route: '/main',
        connectOutlets: function (router, event) {
          router.get('navSurveysController').connectOutlet({
            name: 'navSurveysMain'
          });
          FLOW.projectControl.populate();
          FLOW.projectControl.set('currentProject', null);
          FLOW.projectControl.set('newlyCreated', null);
          FLOW.selectedControl.set('selectedQuestionGroup', null);
          FLOW.selectedControl.set('selectedSurvey', null);
          FLOW.selectedControl.set('selectedQuestion', null);
          FLOW.questionControl.set('OPTIONcontent', null);
          FLOW.attributeControl.populate();

        }
      }),

      navSurveysNew: Ember.Route.extend({
        route: '/new',
        connectOutlets: function (router, event) {
          var newSurvey;

          newSurvey = FLOW.store.createRecord(FLOW.Survey, {
            "name": "",
            "defaultLanguageCode": "en",
            "requireApproval": false,
            "status": "NOT_PUBLISHED",
            "surveyGroupId": FLOW.selectedControl.selectedSurveyGroup.get('keyId'),
            "version":"1.0"
          });

          FLOW.selectedControl.set('selectedSurvey', newSurvey);
          router.transitionTo('navSurveys.navSurveysEdit.index');
        }
      }),

      navSurveysEdit: Ember.Route.extend({
        route: '/edit',
        connectOutlets: function (router, event) {
          router.get('navSurveysController').connectOutlet({
            name: 'navSurveysEdit'
          });
          // all questions should be closed when we enter
          FLOW.selectedControl.set('selectedQuestion', null);
          FLOW.attributeControl.populate();
        },

        doEditQuestions: function (router, event) {
          router.transitionTo('navSurveys.navSurveysEdit.editQuestions');
        },

        index: Ember.Route.extend({
          route: '/',
          redirectsTo: 'editQuestions'
        }),

        manageNotifications: Ember.Route.extend({
          route: '/notifications',
          connectOutlets: function (router, event) {
            router.get('navSurveysEditController').connectOutlet({
              name: 'manageNotifications'
            });
            FLOW.notificationControl.populate();
          }
        }),

        manageTranslations: Ember.Route.extend({
          route: '/translations',
          connectOutlets: function (router, event) {
            router.get('navSurveysEditController').connectOutlet({
              name: 'manageTranslations'
            });
            FLOW.translationControl.populate();
          }
        }),

        editQuestions: Ember.Route.extend({
          route: '/questions',
          connectOutlets: function (router, event) {
            router.get('navSurveysEditController').connectOutlet({
              name: 'editQuestions'
            });

          }
        })
      })
    }),

    //********************** DEVICES ROUTER *******************
    navDevices: Ember.Route.extend({
      route: '/devices',
      connectOutlets: function (router, event) {
        router.get('applicationController').connectOutlet('navDevices');
        router.set('navigationController.selected', 'navDevices');
      },

      doCurrentDevices: function (router, event) {
        router.transitionTo('navDevices.currentDevices');
      },

      doAssignSurveysOverview: function (router, event) {
        router.transitionTo('navDevices.assignSurveysOverview');
      },

      doEditSurveysAssignment: function (router, event) {
        router.transitionTo('navDevices.editSurveysAssignment');
      },

      doSurveyBootstrap: function (router, event) {
        router.transitionTo('navDevices.surveyBootstrap');
      },

      index: Ember.Route.extend({
        route: '/',
        redirectsTo: 'currentDevices'
      }),

      currentDevices: Ember.Route.extend({
        route: '/current-devices',
        connectOutlets: function (router, context) {
          router.get('navDevicesController').connectOutlet('currentDevices');
          router.resetState();
          FLOW.deviceGroupControl.populate();
          FLOW.deviceControl.populate();
          FLOW.surveyAssignmentControl.populate();
          FLOW.surveyGroupControl.populate();
          router.set('devicesSubnavController.selected', 'currentDevices');
        }
      }),

      assignSurveysOverview: Ember.Route.extend({
        route: '/assign-surveys',
        connectOutlets: function (router, context) {
          router.get('navDevicesController').connectOutlet('assignSurveysOverview');
          router.set('devicesSubnavController.selected', 'assignSurveys');
        }
      }),

      editSurveysAssignment: Ember.Route.extend({
        route: '/assign-surveys',
        connectOutlets: function (router, context) {
          router.get('navDevicesController').connectOutlet('editSurveyAssignment');
          router.set('devicesSubnavController.selected', 'assignSurveys');
        }
      }),

      surveyBootstrap: Ember.Route.extend({
        route: '/manual-transfer',
        connectOutlets: function (router, context) {
          router.get('navDevicesController').connectOutlet('surveyBootstrap');
          router.set('devicesSubnavController.selected', 'surveyBootstrap');
        }
      })
    }),

    // ******************* DATA ROUTER ***********************
    navData: Ember.Route.extend({
      route: '/data',
      connectOutlets: function (router, event) {
        router.get('applicationController').connectOutlet('navData');
        router.set('navigationController.selected', 'navData');
      },

      doInspectData: function (router, event) {
        router.transitionTo('navData.inspectData');
      },
      doManageAttributes: function (router, event) {
        router.transitionTo('navData.manageAttributes');
      },
      doBulkUpload: function (router, event) {
        router.transitionTo('navData.bulkUpload');
      },
      doDataCleaning: function (router, event) {
        router.transitionTo('navData.dataCleaning');
      },
      doCascadeResources: function (router, event) {
          router.transitionTo('navData.cascadeResources');
        },
      doMonitoringData: function (router, event) {
        router.transitionTo('navData.monitoringData');
      },

      index: Ember.Route.extend({
        route: '/',
        redirectsTo: 'inspectData'
      }),

      inspectData: Ember.Route.extend({
        route: '/inspectdata',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('inspectData');
          router.set('datasubnavController.selected', 'inspectData');
          router.resetState();
        }
      }),

      manageAttributes: Ember.Route.extend({
        route: '/manageattributes',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('manageAttributes');
          router.set('datasubnavController.selected', 'manageAttributes');
          FLOW.attributeControl.populate();
        }
      }),

      bulkUpload: Ember.Route.extend({
        route: '/bulkupload',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('bulkUpload');
          router.set('datasubnavController.selected', 'bulkUpload');
        }
      }),

      dataCleaning: Ember.Route.extend({
        route: '/datacleaning',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('dataCleaning');
          router.set('datasubnavController.selected', 'dataCleaning');
          router.resetState();
        }
      }),

      cascadeResources: Ember.Route.extend({
          route: '/cascaderesources',
          connectOutlets: function (router, context) {
            router.get('navDataController').connectOutlet('cascadeResources');
            router.set('datasubnavController.selected', 'cascadeResources');
            FLOW.cascadeResourceControl.populate();
          }
        }),

      monitoringData: Ember.Route.extend({
        route: '/monitoringdata',
        connectOutlets: function (router, context) {
          router.get('navDataController').connectOutlet('monitoringData');
          router.set('datasubnavController.selected', 'monitoringData');
          router.resetState();
        }
      }),
    }),

    // ************************** REPORTS ROUTER **********************************
    navReports: Ember.Route.extend({
      route: '/reports',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navReports');
        router.resetState();
        router.set('navigationController.selected', 'navReports');
      },

      doExportReports: function (router, event) {
        router.transitionTo('navReports.exportReports');
      },

      doChartReports: function (router, event) {
        router.transitionTo('navReports.chartReports');
      },

      doStatistics: function(router, event) {
        router.transitionTo('navReports.statistics');
      },

      index: Ember.Route.extend({
        route: '/',
        redirectsTo: 'chartReports'
      }),

      exportReports: Ember.Route.extend({
        route: '/exportreports',
        connectOutlets: function (router, context) {
          router.get('navReportsController').connectOutlet('exportReports');
          router.set('reportsSubnavController.selected', 'exportReports');
          router.resetState();
        }
      }),

      chartReports: Ember.Route.extend({
        route: '/chartreports',
        connectOutlets: function (router, context) {
          router.resetState();
          router.get('navReportsController').connectOutlet('chartReports');
          router.set('reportsSubnavController.selected', 'chartReports');
        }
      }),
      statistics: Ember.Route.extend({
        route: '/statistics',
        connectOutlets: function(router, context) {
          router.resetState();
          router.get('navReportsController').connectOutlet('statistics');
          router.set('reportsSubnavController.selected', 'statistics');
          FLOW.surveyGroupControl.populate();
        }
      })
    }),

    // ************************** MAPS ROUTER **********************************
    navMaps: Ember.Route.extend({
      route: '/maps',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navMaps');
        router.set('navigationController.selected', 'navMaps');
      }
    }),

    // ************************** USERS ROUTER **********************************
    navUsers: Ember.Route.extend({
      route: '/users',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navUsers');
        router.set('navigationController.selected', 'navUsers');
        FLOW.userControl.populate();
      }
    }),

    // ************************** MESSAGES ROUTER **********************************
    navMessages: Ember.Route.extend({
      route: '/users',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navMessages');
        router.set('navigationController.selected', 'navMessages');
        FLOW.messageControl.populate();
        router.resetState();
      }
    }),

    // ************************** ADMIN ROUTER **********************************
    // not used at the moment
    navAdmin: Ember.Route.extend({
      route: '/admin',
      connectOutlets: function (router, context) {
        router.get('applicationController').connectOutlet('navAdmin');
        router.set('navigationController.selected', 'navAdmin');
      }
    })
  })
});
<|endoftext|>


<commit_before>
'use strict'

const _ = require('lodash')
const config = require('../config')
const commands = _.reduce(fs.readdirSync(__dirname), (a, file) => {
  if (file !== 'index.js') a.push(require(`./${file}`))

  return a
}, [])

const msgDefaults = {
  response_type: 'in_channel',
  username: 'Stubot',
  icon_emoji: config('ICON_EMOJI')
}

var getCommands(commands) {
	let cmdString = _.reduce(commands, (string, cmd) => {
		return string + cmd + ', ';
	}, "");

	return cmdString;
}

let attachments = [
  {
  	title: 'List of commands',
	text: getCommands(commands),
	mrkdwn_in: ['text']
  },
  {
    title: 'Stubot will help you find the flyest repos on GitHub',
    color: '#2FA44F',
    text: '`/stubot repos` returns hip repos \n`/stubot javascript` returns hip JavaScript repos',
    mrkdwn_in: ['text']
  },
  {
    title: 'Configuring Stubot',
    color: '#E3E4E6',
    text: '`/stubot help` ... you\'re lookin at it! \n',
    mrkdwn_in: ['text']
  }
]

const handler = (payload, res) => {
  let msg = _.defaults({
    channel: payload.channel_name,
    attachments: attachments
  }, msgDefaults)

  res.set('content-type', 'application/json')
  res.status(200).json(msg)
  return
}

module.exports = { pattern: /help/ig, handler: handler }
<commit_msg>adjustment to make command list work.<commit_after>
'use strict'

const _ = require('lodash')
const config = require('../config')
const commands = _.reduce(fs.readdirSync(__dirname), (a, file) => {
  if (file !== 'index.js') a.push(require(`./${file}`))

  return a
}, [])

const msgDefaults = {
  response_type: 'in_channel',
  username: 'Stubot',
  icon_emoji: config('ICON_EMOJI')
}

function getCommands(commands) {
	let cmdString = _.reduce(commands, (string, cmd) => {
		return string + cmd + ', ';
	}, "");

	return cmdString;
}

let attachments = [
  {
  	title: 'List of commands',
	text: getCommands(commands),
	mrkdwn_in: ['text']
  },
  {
    title: 'Stubot will help you find the flyest repos on GitHub',
    color: '#2FA44F',
    text: '`/stubot repos` returns hip repos \n`/stubot javascript` returns hip JavaScript repos',
    mrkdwn_in: ['text']
  },
  {
    title: 'Configuring Stubot',
    color: '#E3E4E6',
    text: '`/stubot help` ... you\'re lookin at it! \n',
    mrkdwn_in: ['text']
  }
]

const handler = (payload, res) => {
  let msg = _.defaults({
    channel: payload.channel_name,
    attachments: attachments
  }, msgDefaults)

  res.set('content-type', 'application/json')
  res.status(200).json(msg)
  return
}

module.exports = { pattern: /help/ig, handler: handler }
<|endoftext|>


<commit_before>import inquirer from 'inquirer';
import ProgressBar from 'progress';
import { Api, Exp, Logger, NotificationCode, MessageCode } from 'xdl';

import _ from 'lodash';
import log from '../log';
import CommandError from '../CommandError';

import path from 'path';

let _currentRequestID = 0;
let _downloadIsSlowPrompt = false;
let _retryObject = {};
let _bar = new ProgressBar('[:bar] :percent', {
  total: 100,
  complete: '=',
  incomplete: ' ',
});

async function action(projectDir, options) {
  let templateType;
  let questions = [];

  let insertPath = path.dirname(projectDir);
  let name = path.basename(projectDir);

  // If the user does not supply a project name, exp prompts the user
  if (projectDir === process.cwd()) {
    questions.push({
      name: 'name',
      message: 'Choose a project name:',
      validate(input) {
        return /^[a-z0-9@.' '\-\_]*$/i.test(input) && input.length > 0;
      },
    });
  }

  if (options.projectType) {
    templateType = options.projectType;
  } else {
    let versions = await Api.versionsAsync();
    let templateIds = _.map(versions.templatesv2, template => template.id);

    questions.push({
      type: 'list',
      name: 'type',
      message: 'Choose a template type:',
      choices: templateIds,
    });
  }

  if (questions.length > 0) {
    var answers = await inquirer.prompt(questions);
    if (answers.name) {
      // If the user supplies a project name, change the insertPath and name
      insertPath = projectDir;
      name = answers.name;
    }
    if (answers.type) {
      templateType = answers.type;
    }
  }

  if (!insertPath || !name) {
    throw new CommandError(
      'PATH_ERROR',
      `Couldn't determine path for new project.`
    );
  }

  // TODO(jim): We will need to update this method later to not force
  // us to strip out the <name> from /path/to/<name> if we don't want
  // to duplicate the folder at creation time. (example: test => test/test)
  await downloadAndExtractTemplate(templateType, insertPath, {
    name,
  });
}

async function downloadAndExtractTemplate(
  templateType,
  projectDir,
  validatedOptions
) {
  _retryObject = { templateType, projectDir, validatedOptions };
  const requestID = _currentRequestID + 1;
  _currentRequestID = requestID;

  let templateDownload = await Exp.downloadTemplateApp(
    templateType,
    projectDir,
    {
      ...validatedOptions,
      progressFunction: progress => {
        if (_currentRequestID === requestID) {
          Logger.notifications.info(
            { code: NotificationCode.DOWNLOAD_CLI_PROGRESS },
            progress + '%'
          );
          if (!_downloadIsSlowPrompt) {
            _bar.tick();
          }
        }
      },
      retryFunction: () => {
        triggerRetryPrompt();
      },
    }
  );

  // Since we cannot cancel the download request, we need a way to ignore all of the requests made except the last one when retrying.
  if (_currentRequestID !== requestID) {
    return;
  }
  let root = await Exp.extractTemplateApp(
    templateDownload.starterAppPath,
    templateDownload.name,
    templateDownload.root
  );
  log(
    `Your project is ready at ${root}. Use "exp start ${root}" to get started.`
  );
  process.exit();
}

async function triggerRetryPrompt() {
  _downloadIsSlowPrompt = true;
  var answer = await inquirer({
    type: 'input',
    name: 'retry',
    message: '\n' + MessageCode.DOWNLOAD_IS_SLOW + '(y/n)',
    validate(val) {
      if (val !== 'y' && val !== 'n') {
        return false;
      }
      return true;
    },
  });

  if (answer.retry === 'n') {
    _downloadIsSlowPrompt = false;
  } else {
    Exp.clearXDLCacheAsync();
    _downloadIsSlowPrompt = false;
    downloadAndExtractTemplate(
      _retryObject.templateType,
      _retryObject.projectDir,
      _retryObject.validatedOptions
    );
  }
}

export default program => {
  program
    .command('init [project-dir]')
    .alias('i')
    .description(
      'Initializes a directory with an example project. Run it without any options and you will be prompted for the name and type.'
    )
    .option(
      '-t, --projectType [type]',
      'Specify what type of template to use. Run without this option to see all choices.'
    )
    .allowNonInteractive()
    .asyncActionProjectDir(action, true /* skipProjectValidation */);
};
<commit_msg>Revert "[devtools] Use Chromium's XMLHttpRequest in XDE, Node's http in exp (#1057)"<commit_after>import inquirer from 'inquirer';
import ProgressBar from 'progress';
import { Api, Exp, Logger, NotificationCode, MessageCode } from 'xdl';

import _ from 'lodash';
import log from '../log';
import CommandError from '../CommandError';

import path from 'path';

let _currentRequestID = 0;
let _downloadIsSlowPrompt = false;
let _retryObject = {};

async function action(projectDir, options) {
  let templateType;
  let questions = [];

  let insertPath = path.dirname(projectDir);
  let name = path.basename(projectDir);

  // If the user does not supply a project name, exp prompts the user
  if (projectDir === process.cwd()) {
    questions.push({
      name: 'name',
      message: 'Choose a project name:',
      validate(input) {
        return /^[a-z0-9@.' '\-\_]*$/i.test(input) && input.length > 0;
      },
    });
  }

  if (options.projectType) {
    templateType = options.projectType;
  } else {
    let versions = await Api.versionsAsync();
    let templateIds = _.map(versions.templatesv2, template => template.id);

    questions.push({
      type: 'list',
      name: 'type',
      message: 'Choose a template type:',
      choices: templateIds,
    });
  }

  if (questions.length > 0) {
    var answers = await inquirer.prompt(questions);
    if (answers.name) {
      // If the user supplies a project name, change the insertPath and name
      insertPath = projectDir;
      name = answers.name;
    }
    if (answers.type) {
      templateType = answers.type;
    }
  }

  if (!insertPath || !name) {
    throw new CommandError(
      'PATH_ERROR',
      `Couldn't determine path for new project.`
    );
  }

  // TODO(jim): We will need to update this method later to not force
  // us to strip out the <name> from /path/to/<name> if we don't want
  // to duplicate the folder at creation time. (example: test => test/test)
  await downloadAndExtractTemplate(templateType, insertPath, {
    name,
  });
}

async function downloadAndExtractTemplate(
  templateType,
  projectDir,
  validatedOptions
) {
  _retryObject = { templateType, projectDir, validatedOptions };
  const requestID = _currentRequestID + 1;
  _currentRequestID = requestID;
  let templateDownload = await Exp.downloadTemplateApp(
    templateType,
    projectDir,
    {
      ...validatedOptions,
      progressFunction: progress => {
        const percent = Math.round(progress * 100);
        if (_currentRequestID === requestID) {
          Logger.notifications.info(
            { code: NotificationCode.DOWNLOAD_CLI_PROGRESS },
            percent + '%'
          );
          const bar = new ProgressBar('[:bar] :percent', {
            total: 100,
            complete: '=',
            incomplete: ' ',
          });
          if (!_downloadIsSlowPrompt) {
            bar.tick(percent);
          }
        }
      },
      retryFunction: () => {
        triggerRetryPrompt();
      },
    }
  );

  // Since we cannot cancel the download request, we need a way to ignore all of the requests made except the last one when retrying.
  if (_currentRequestID !== requestID) {
    return;
  }
  let root = await Exp.extractTemplateApp(
    templateDownload.starterAppPath,
    templateDownload.name,
    templateDownload.root
  );
  log(
    `Your project is ready at ${root}. Use "exp start ${root}" to get started.`
  );
  process.exit();
}

async function triggerRetryPrompt() {
  _downloadIsSlowPrompt = true;
  var answer = await inquirer({
    type: 'input',
    name: 'retry',
    message: '\n' + MessageCode.DOWNLOAD_IS_SLOW + '(y/n)',
    validate(val) {
      if (val !== 'y' && val !== 'n') {
        return false;
      }
      return true;
    },
  });

  if (answer.retry === 'n') {
    _downloadIsSlowPrompt = false;
  } else {
    Exp.clearXDLCacheAsync();
    _downloadIsSlowPrompt = false;
    downloadAndExtractTemplate(
      _retryObject.templateType,
      _retryObject.projectDir,
      _retryObject.validatedOptions
    );
  }
}

export default program => {
  program
    .command('init [project-dir]')
    .alias('i')
    .description(
      'Initializes a directory with an example project. Run it without any options and you will be prompted for the name and type.'
    )
    .option(
      '-t, --projectType [type]',
      'Specify what type of template to use. Run without this option to see all choices.'
    )
    .allowNonInteractive()
    .asyncActionProjectDir(action, true /* skipProjectValidation */);
};
<|endoftext|>


<commit_before>const camera = {
  projection: new Float32Array(16),
  view: new Float32Array(16),

  thetaDelta: 0,
  phiDelta: 0,
  scale: 1,

  position: [450, 300, 200],
  target: [0, 0, 0]
}

// below this, dynamic stuff mostly, since this is also the ouput of the controls function
/*camera: {

  //view: mat4.create() // default, this is just a 4x4 matrix
}*/

export default camera
<commit_msg>feat(camera): adjusted default camera position<commit_after>const camera = {
  projection: new Float32Array(16),
  view: new Float32Array(16),

  thetaDelta: 0,
  phiDelta: 0,
  scale: 1,

  position: [150, 250, 200],
  target: [0, 0, 0]
}

// below this, dynamic stuff mostly, since this is also the ouput of the controls function
/*camera: {

  //view: mat4.create() // default, this is just a 4x4 matrix
}*/

export default camera
<|endoftext|>


<commit_before>/* eslint-disable no-unused-vars */
const $ = require('jquery');
const _ = require('lodash');
const qw = require('qw');
const ga = require('./ga.js');
const constants = require('./constants.js');
const moment = require('moment');

function getEntityId(href) {
    let entityId = getQueryArgs(href).entityId;
    if (entityId) {
        return entityId;
    }

    let navLink = $('.topNavLogo')[0].href;
    let query = navLink.substring(navLink.indexOf('?') + 1);
    entityId = getQueryArgs(query).entityId;
    if (entityId) {
        return entityId;
    }

    throw ga.merror('could not discover entityId');
}

function getCampaignId(href) {
    let campaignId = getQueryArgs(href).campaignId;
    if (campaignId) {
        return campaignId;
    }

    campaignId = $('input[name=campaignId]').val();
    if (campaignId) {
        return campaignId;
    }

    throw ga.merror('could not discover entityId');
}

function getSellerCampaignId(href) {
    let path = href.split('?')[0];
    let parts = path.split('/');
    let campaignIdx = parts.indexOf('campaign');
    let adGroupIdx = parts.indexOf('ad_group');
    return {
        campaignId: campaignIdx >= 0 ? parts[campaignIdx + 1] : null,
        adGroupId: adGroupIdx >= 0 ? parts[adGroupIdx + 1] : null,
    };
}

function getAsin(url) {
    let path = url.split('?')[0];
    let parts = path.split('/');

    // ASIN is 10 characters beginning with B. If there's only one of those,
    // return it immediately.
    let asinLookalikes = parts.filter(x => x.length == 10 && x[0] == 'B');
    if (!asinLookalikes.length)
        return null;
    if (asinLookalikes.length == 1)
        return asinLookalikes[0];

    // Look for url patterns like product/${ASIN}
    let productIdx = parts.indexOf('product');
    if (productIdx >= 0 && asinLookalikes.includes(parts[productIdx + 1]))
        return parts[productIdx + 1];

    // Look for url patterns like dp/${ASIN}
    let dpIdx = parts.indexOf('dp');
    if (dpIdx >= 0 && asinLookalikes.includes(parts[dpIdx + 1]))
        return parts[dpIdx + 1];

    // Just return the first ASIN-like thing and hope for the best. This returns
    // undefined if there were *no* ASINs found.
    return asinLookalikes[0];
}

function getQueryArgs(str) {
    let qstring = str || window.location.toString();
    qstring = qstring.split('?').pop();
    if (qstring.includes('#')) {
        qstring = qstring.substring(0, qstring.lastIndexOf('#'));
    }

    let qs = qstring.split('&');
    let args = {};
    for (let q of qs) {
        let parts = q.split('=');
        args[parts[0]] = parts[1];
    }
    return args;
}

function moneyFmt(val) {
    if (Number.isNaN(+val)) {
        return '--';
    }
    return `$${(+val).toFixed(2)}`;
}

function pctFmt(val) {
    if (Number.isNaN(+val)) {
        return '--';
    }
    return `${(+val).toFixed(2)}%`;
}

const cumulativeMetrics = qw`impressions clicks salesCount salesValue spend`;
const aggregateMetrics = qw`ctr acos avgCpc`;

// Convert a series of objects into a single object with a number of parallel
// arrays. All objects in the series should have the same keys; in any case,
// only the keys from the first object in the series are respected.
function parallelizeSeries(data) {
    let c = { timestamp: [] };
    if (!data || !data.length)
        return c;

    _.keys(data[0]).forEach(key => c[key] = []);

    for (let item of data) {
        for (let key of _.keys(c)) {
            if (key == 'timestamp')
                c[key].push(new Date(item[key]));
            else
                c[key].push(item[key]);
        }
    }

    return c;
}

// Convert a series of timestamped snapshots into a series of objects in which
// each key has the difference from the previous snapshot, ie. the rate of
// change between snapshots. Only the metrics found in `cumulativeMetrics` are
// converted into rates. The opt object has the following relevant keys:
//      chunk: round timestamps off to the nearest hour/day/etc. and only
//          compare values that cross a chunk boundary.
//      rate: the timespn over which to calculate rates. Should generally be the
//          same as chunk, when present.
//      startTimestamp: earliest timestamp to examine. Items outside of this
//          range are discarded.
//      endTimestamp: latest timestamp to examine. Items outside of this range
//          are discarded.
//      round: if true, then fractional values are rounded to the nearest whole
//          value
function convertSnapshotsToDeltas(data, opt) {
    let c = [];
    opt = opt || {};

    let lastItem = null;
    data = data.sort((a, b) => a.timestamp - b.timestamp);
    for (let item of data) {
        if (opt.chunk) {
            if (lastItem && moment(item.timestamp).isSame(moment(lastItem.timestamp), opt.chunk)) {
                continue;
            }
            item.timestamp = moment(item.timestamp).startOf(opt.chunk);
        }

        // Filter out things by date range
        if (opt.startTimestamp && item.timestamp < opt.startTimestamp) {
            continue;
        }
        if (opt.endTimestamp && item.timestamp > opt.endTimestamp) {
            continue;
        }

        // Skip this data point unless one of our metrics actually changed.
        if (lastItem && !cumulativeMetrics.some(metric => item[metric] != lastItem[metric])) {
            continue;
        }

        if (lastItem) {
            const delta = Object.assign({}, item);
            for (let metric of cumulativeMetrics) {
                let rateFactor = (item.timestamp - lastItem.timestamp)/constants.timespan[opt.rate];
                let normalized = (item[metric] - lastItem[metric])/rateFactor;
                if (opt.round)
                    normalized = Math.round(normalized);
                delta[metric] = normalized;
            }
            c.push(delta);
        }

        lastItem = item;
    }

    return c;
}

function getCampaignHistory(entityId, campaignId, cb) {
    chrome.runtime.sendMessage({
        action: 'getDataHistory',
        entityId: entityId,
        campaignId: campaignId,
    },
    ga.mcatch(response => {
        if (response.error) {
            ga.merror(response.status, response.error);
            return;
        }
        cb(response.data);
    }));
}

let allowedPromise = null;
function getAllowedCampaigns(entityId) {
    if (!allowedPromise) {
        allowedPromise = ga.mpromise((resolve, reject) => {
            chrome.runtime.sendMessage({
                action: 'getAllowedCampaigns',
                entityId
            }, response => {
                if (response.error) {
                    return reject(response.error);
                }
                return resolve(response.data);
            });
        });
    }

    return allowedPromise;
}

function getCampaignAllowed(entityId, campaignId) {
    return getAllowedCampaigns(entityId).then(allowed => {
        if (allowed[0] == '*') {
            return true;
        }
        return allowed.includes(campaignId);
    });
}

let getUserPromise = null;
function getUser() {
    if (!getUserPromise) {
        getUserPromise = ga.mpromise(resolve => {
            chrome.runtime.sendMessage({ action: 'getUser' }, response => {
                if (response.error) {
                    ga.merror(response.error);
                }
                const user = response.data || { email: 'anon-user-email', activeSubscription: { name: 'Machete Free' } };
                let email = user.email;
                user.isAnon = email == 'anon-user-email';
                resolve(user);
            });
        });
    }
    return getUserPromise;
}

if (window.location.href.includes('ams')) {
    chrome.runtime.sendMessage({
        action: 'setSession',
        entityId: getEntityId(),
    }, response => console.log('setSession success'));

    getUser().then(user => {
        const desc = user.activeSubscription.name;
        let email = user.email;
        let profileText = "Your Profile";
        let label = 'view-profile';
        if (user.isAnon) {
            email = '';
            profileText = 'Login/Register';
            label = 'login';
        }
        let links = $('.userBarLinksRight');
        if (links[0]) {
            let chunks = links[0].innerHTML.split(' | ');
            chunks.splice(-1, 0, `${desc} (<a data-mclick="machete-status ${label}" title="${email}" href="https://${constants.hostname}/profile" target="_blank">${profileText}</a>)`);
            links[0].innerHTML = chunks.join(' | ');
        }
        let logout = links.find('a');
        if (logout[1]) {
            $(logout[1]).click(() => {
                const result = confirm(
                    `Logging out of AMS will prevent Machete from monitoring your campaigns. Instead, you may close this tab without logging out.

                    Continue logging out?`);
                return result;
            });
        }
    });
}

module.exports = {
    getEntityId,
    getCampaignId,
    getSellerCampaignId,
    getQueryArgs,
    getAsin,
    getCampaignAllowed,
    getUser,
    moneyFmt,
    pctFmt,
    getCampaignHistory,
    parallelizeSeries,
    convertSnapshotsToDeltas,
};
<commit_msg>added an isSeller property to the client-side user object to be able to identify seller accounts<commit_after>/* eslint-disable no-unused-vars */
const $ = require('jquery');
const _ = require('lodash');
const qw = require('qw');
const ga = require('./ga.js');
const constants = require('./constants.js');
const moment = require('moment');

function getEntityId(href) {
    let entityId = getQueryArgs(href).entityId;
    if (entityId) {
        return entityId;
    }

    let navLink = $('.topNavLogo')[0].href;
    let query = navLink.substring(navLink.indexOf('?') + 1);
    entityId = getQueryArgs(query).entityId;
    if (entityId) {
        return entityId;
    }

    throw ga.merror('could not discover entityId');
}

function getCampaignId(href) {
    let campaignId = getQueryArgs(href).campaignId;
    if (campaignId) {
        return campaignId;
    }

    campaignId = $('input[name=campaignId]').val();
    if (campaignId) {
        return campaignId;
    }

    throw ga.merror('could not discover entityId');
}

function getSellerCampaignId(href) {
    let path = href.split('?')[0];
    let parts = path.split('/');
    let campaignIdx = parts.indexOf('campaign');
    let adGroupIdx = parts.indexOf('ad_group');
    return {
        campaignId: campaignIdx >= 0 ? parts[campaignIdx + 1] : null,
        adGroupId: adGroupIdx >= 0 ? parts[adGroupIdx + 1] : null,
    };
}

function getAsin(url) {
    let path = url.split('?')[0];
    let parts = path.split('/');

    // ASIN is 10 characters beginning with B. If there's only one of those,
    // return it immediately.
    let asinLookalikes = parts.filter(x => x.length == 10 && x[0] == 'B');
    if (!asinLookalikes.length)
        return null;
    if (asinLookalikes.length == 1)
        return asinLookalikes[0];

    // Look for url patterns like product/${ASIN}
    let productIdx = parts.indexOf('product');
    if (productIdx >= 0 && asinLookalikes.includes(parts[productIdx + 1]))
        return parts[productIdx + 1];

    // Look for url patterns like dp/${ASIN}
    let dpIdx = parts.indexOf('dp');
    if (dpIdx >= 0 && asinLookalikes.includes(parts[dpIdx + 1]))
        return parts[dpIdx + 1];

    // Just return the first ASIN-like thing and hope for the best. This returns
    // undefined if there were *no* ASINs found.
    return asinLookalikes[0];
}

function getQueryArgs(str) {
    let qstring = str || window.location.toString();
    qstring = qstring.split('?').pop();
    if (qstring.includes('#')) {
        qstring = qstring.substring(0, qstring.lastIndexOf('#'));
    }

    let qs = qstring.split('&');
    let args = {};
    for (let q of qs) {
        let parts = q.split('=');
        args[parts[0]] = parts[1];
    }
    return args;
}

function moneyFmt(val) {
    if (Number.isNaN(+val)) {
        return '--';
    }
    return `$${(+val).toFixed(2)}`;
}

function pctFmt(val) {
    if (Number.isNaN(+val)) {
        return '--';
    }
    return `${(+val).toFixed(2)}%`;
}

const cumulativeMetrics = qw`impressions clicks salesCount salesValue spend`;
const aggregateMetrics = qw`ctr acos avgCpc`;

// Convert a series of objects into a single object with a number of parallel
// arrays. All objects in the series should have the same keys; in any case,
// only the keys from the first object in the series are respected.
function parallelizeSeries(data) {
    let c = { timestamp: [] };
    if (!data || !data.length)
        return c;

    _.keys(data[0]).forEach(key => c[key] = []);

    for (let item of data) {
        for (let key of _.keys(c)) {
            if (key == 'timestamp')
                c[key].push(new Date(item[key]));
            else
                c[key].push(item[key]);
        }
    }

    return c;
}

// Convert a series of timestamped snapshots into a series of objects in which
// each key has the difference from the previous snapshot, ie. the rate of
// change between snapshots. Only the metrics found in `cumulativeMetrics` are
// converted into rates. The opt object has the following relevant keys:
//      chunk: round timestamps off to the nearest hour/day/etc. and only
//          compare values that cross a chunk boundary.
//      rate: the timespn over which to calculate rates. Should generally be the
//          same as chunk, when present.
//      startTimestamp: earliest timestamp to examine. Items outside of this
//          range are discarded.
//      endTimestamp: latest timestamp to examine. Items outside of this range
//          are discarded.
//      round: if true, then fractional values are rounded to the nearest whole
//          value
function convertSnapshotsToDeltas(data, opt) {
    let c = [];
    opt = opt || {};

    let lastItem = null;
    data = data.sort((a, b) => a.timestamp - b.timestamp);
    for (let item of data) {
        if (opt.chunk) {
            if (lastItem && moment(item.timestamp).isSame(moment(lastItem.timestamp), opt.chunk)) {
                continue;
            }
            item.timestamp = moment(item.timestamp).startOf(opt.chunk);
        }

        // Filter out things by date range
        if (opt.startTimestamp && item.timestamp < opt.startTimestamp) {
            continue;
        }
        if (opt.endTimestamp && item.timestamp > opt.endTimestamp) {
            continue;
        }

        // Skip this data point unless one of our metrics actually changed.
        if (lastItem && !cumulativeMetrics.some(metric => item[metric] != lastItem[metric])) {
            continue;
        }

        if (lastItem) {
            const delta = Object.assign({}, item);
            for (let metric of cumulativeMetrics) {
                let rateFactor = (item.timestamp - lastItem.timestamp)/constants.timespan[opt.rate];
                let normalized = (item[metric] - lastItem[metric])/rateFactor;
                if (opt.round)
                    normalized = Math.round(normalized);
                delta[metric] = normalized;
            }
            c.push(delta);
        }

        lastItem = item;
    }

    return c;
}

function getCampaignHistory(entityId, campaignId, cb) {
    chrome.runtime.sendMessage({
        action: 'getDataHistory',
        entityId: entityId,
        campaignId: campaignId,
    },
    ga.mcatch(response => {
        if (response.error) {
            ga.merror(response.status, response.error);
            return;
        }
        cb(response.data);
    }));
}

let allowedPromise = null;
function getAllowedCampaigns(entityId) {
    if (!allowedPromise) {
        allowedPromise = ga.mpromise((resolve, reject) => {
            chrome.runtime.sendMessage({
                action: 'getAllowedCampaigns',
                entityId
            }, response => {
                if (response.error) {
                    return reject(response.error);
                }
                return resolve(response.data);
            });
        });
    }

    return allowedPromise;
}

function getCampaignAllowed(entityId, campaignId) {
    return getAllowedCampaigns(entityId).then(allowed => {
        if (allowed[0] == '*') {
            return true;
        }
        return allowed.includes(campaignId);
    });
}

let getUserPromise = null;
function getUser() {
    if (!getUserPromise) {
        getUserPromise = ga.mpromise(resolve => {
            chrome.runtime.sendMessage({ action: 'getUser' }, response => {
                if (response.error) {
                    ga.merror(response.error);
                }
                const user = response.data || { email: 'anon-user-email', activeSubscription: { id: 'free', name: 'Machete Free' } };
                user.isAnon = user.email == 'anon-user-email';
                user.isSeller = user.activeSubscription.id == 'seller';
                resolve(user);
            });
        });
    }
    return getUserPromise;
}

if (window.location.href.includes('ams')) {
    chrome.runtime.sendMessage({
        action: 'setSession',
        entityId: getEntityId(),
    }, response => console.log('setSession success'));

    getUser().then(user => {
        const desc = user.activeSubscription.name;
        let email = user.email;
        let profileText = "Your Profile";
        let label = 'view-profile';
        if (user.isAnon) {
            email = '';
            profileText = 'Login/Register';
            label = 'login';
        }
        let links = $('.userBarLinksRight');
        if (links[0]) {
            let chunks = links[0].innerHTML.split(' | ');
            chunks.splice(-1, 0, `${desc} (<a data-mclick="machete-status ${label}" title="${email}" href="https://${constants.hostname}/profile" target="_blank">${profileText}</a>)`);
            links[0].innerHTML = chunks.join(' | ');
        }
        let logout = links.find('a');
        if (logout[1]) {
            $(logout[1]).click(() => {
                const result = confirm(
                    `Logging out of AMS will prevent Machete from monitoring your campaigns. Instead, you may close this tab without logging out.

                    Continue logging out?`);
                return result;
            });
        }
    });
}

module.exports = {
    getEntityId,
    getCampaignId,
    getSellerCampaignId,
    getQueryArgs,
    getAsin,
    getCampaignAllowed,
    getUser,
    moneyFmt,
    pctFmt,
    getCampaignHistory,
    parallelizeSeries,
    convertSnapshotsToDeltas,
};
<|endoftext|>


<commit_before>/*
 * ImageLoader
 * Visit http://createjs.com/ for documentation, updates and examples.
 *
 *
 * Copyright (c) 2012 gskinner.com, inc.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

// namespace:
this.createjs = this.createjs || {};

(function () {
	"use strict";

	// constructor
	/**
	 * A loader for image files.
	 * @class ImageLoader
	 * @param {LoadItem|Object} loadItem
	 * @param {Boolean} preferXHR
	 * @constructor
	 */
	function ImageLoader (loadItem, preferXHR) {
		this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.IMAGE);

		// public properties
		this.resultFormatter = this._formatResult;

		// protected properties
		this._tagSrcAttribute = "src";

		// Check if the preload item is already a tag.
		if (createjs.RequestUtils.isImageTag(loadItem)) {
			this._tag = loadItem;
		} else if (createjs.RequestUtils.isImageTag(loadItem.src)) {
			this._tag = loadItem.src;
		} else if (createjs.RequestUtils.isImageTag(loadItem.tag)) {
			this._tag = loadItem.tag;
		}

		if (this._tag != null) {
			this._preferXHR = false;
		} else {
			this._tag = document.createElement("img");
		}

		this.on("initialize", this._updateXHR, this);
	};

	var p = createjs.extend(ImageLoader, createjs.AbstractLoader);
	var s = ImageLoader;

	// static methods
	/**
	 * Determines if the loader can load a specific item. This loader can only load items that are of type
	 * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}.
	 * @method canLoadItem
	 * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
	 * @returns {Boolean} Whether the loader can load the item.
	 * @static
	 */
	s.canLoadItem = function (item) {
		return item.type == createjs.AbstractLoader.IMAGE;
	};

	// public methods
	p.load = function () {
		if (this._tag.src != "" && this._tag.complete) {
			this._sendComplete();
			return;
		}

		if (this._preferXHR && this._item.crossOrigin != null) {
			this._tag.crossOrigin = this._item.crossOrigin;
		}
		this.AbstractLoader_load();
	};

	// protected methods
	/**
	 * Before the item loads, set its mimetype and responseType.
	 * @property _updateXHR
	 * @param {Event} event
	 * @private
	 */
	p._updateXHR = function (event) {
		event.loader.mimeType = 'text/plain; charset=x-user-defined-binary';

		// Only exists for XHR
		if (event.loader.setResponseType) {
			event.loader.setResponseType("blob");
		}
	};

	/**
	 * The result formatter for Image files.
	 * @method _formatResult
	 * @param {AbstractLoader} loader
	 * @returns {HTMLImageElement}
	 * @private
	 */
	p._formatResult = function (loader) {
		var _this = this;
		return function (done) {
			var tag = _this._tag;
			var URL = window.URL || window.webkitURL;

			if (!_this._preferXHR) {
				//document.body.removeChild(tag);
			} else if (URL) {
				var objURL = URL.createObjectURL(loader.getResult(true));
				tag.src = objURL;
				tag.onload = function () {
					URL.revokeObjectURL(_this.src);
				}
			} else {
				tag.src = loader.getItem().src;
			}

			if (tag.complete) {
				done(tag);
			} else {
				tag.onload = function () {
					done(this);
				}
			}
		};
	};

	createjs.ImageLoader = createjs.promote(ImageLoader, "AbstractLoader");

}());
<commit_msg>Added isLocal() check to ImageLoader, so we don't set crossOrigin when loading local images.<commit_after>/*
 * ImageLoader
 * Visit http://createjs.com/ for documentation, updates and examples.
 *
 *
 * Copyright (c) 2012 gskinner.com, inc.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

// namespace:
this.createjs = this.createjs || {};

(function () {
	"use strict";

	// constructor
	/**
	 * A loader for image files.
	 * @class ImageLoader
	 * @param {LoadItem|Object} loadItem
	 * @param {Boolean} preferXHR
	 * @constructor
	 */
	function ImageLoader (loadItem, preferXHR) {
		this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.IMAGE);

		// public properties
		this.resultFormatter = this._formatResult;

		// protected properties
		this._tagSrcAttribute = "src";

		// Check if the preload item is already a tag.
		if (createjs.RequestUtils.isImageTag(loadItem)) {
			this._tag = loadItem;
		} else if (createjs.RequestUtils.isImageTag(loadItem.src)) {
			this._tag = loadItem.src;
		} else if (createjs.RequestUtils.isImageTag(loadItem.tag)) {
			this._tag = loadItem.tag;
		}

		if (this._tag != null) {
			this._preferXHR = false;
		} else {
			this._tag = document.createElement("img");
		}

		this.on("initialize", this._updateXHR, this);
	};

	var p = createjs.extend(ImageLoader, createjs.AbstractLoader);
	var s = ImageLoader;

	// static methods
	/**
	 * Determines if the loader can load a specific item. This loader can only load items that are of type
	 * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}.
	 * @method canLoadItem
	 * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
	 * @returns {Boolean} Whether the loader can load the item.
	 * @static
	 */
	s.canLoadItem = function (item) {
		return item.type == createjs.AbstractLoader.IMAGE;
	};

	// public methods
	p.load = function () {
		if (this._tag.src != "" && this._tag.complete) {
			this._sendComplete();
			return;
		}

		if (!createjs.RequestUtils.isLocal(this._item.src) && this._item.crossOrigin != null) {
			this._tag.crossOrigin = this._item.crossOrigin;
		}

		this.AbstractLoader_load();
	};

	// protected methods
	/**
	 * Before the item loads, set its mimetype and responseType.
	 * @property _updateXHR
	 * @param {Event} event
	 * @private
	 */
	p._updateXHR = function (event) {
		event.loader.mimeType = 'text/plain; charset=x-user-defined-binary';

		// Only exists for XHR
		if (event.loader.setResponseType) {
			event.loader.setResponseType("blob");
		}
	};

	/**
	 * The result formatter for Image files.
	 * @method _formatResult
	 * @param {AbstractLoader} loader
	 * @returns {HTMLImageElement}
	 * @private
	 */
	p._formatResult = function (loader) {
		var _this = this;
		return function (done) {
			var tag = _this._tag;
			var URL = window.URL || window.webkitURL;

			if (!_this._preferXHR) {
				//document.body.removeChild(tag);
			} else if (URL) {
				var objURL = URL.createObjectURL(loader.getResult(true));
				tag.src = objURL;
				tag.onload = function () {
					URL.revokeObjectURL(_this.src);
				}
			} else {
				tag.src = loader.getItem().src;
			}

			if (tag.complete) {
				done(tag);
			} else {
				tag.onload = function () {
					done(this);
				}
			}
		};
	};

	createjs.ImageLoader = createjs.promote(ImageLoader, "AbstractLoader");

}());
<|endoftext|>


<commit_before>define(['jquery', 'bootstrap'], function ($) {
  'use strict';
  var my = {};

  my.dateTimeFormat = {year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric'};

  my.formatClaim = function (el) {
    el.html(function (claimedObject) {
      var claim = claimedObject.claim;
      if (claim.claimed) {
        return ' ' + (claim.reason ? (' ' + claim.reason + '
 ') : '') +
          ' ' + claim.claimedBy + '' +
          ' ' + new Date(claim.claimDate).toLocaleString('de-DE', my.dateTimeFormat) + '';
      } else {
        return '';
      }
    });
  };

  var appendTestCaseDetails = function (name, description, present, collapse, text) {
    return function (hull) {
      hull
        .filter(present)
        .append("div").call(function (div) {
          div.append("h6")
            .append("a")
            .attr("data-toggle", "collapse")
            .attr("href", function (testCase) {
              return "#" + name + testCase.id;
            })
            .text(description)
            .append("span")
            .attr("class", "caret")
          ;
        })
        .append("div")
        .attr("class", function (testCase) {
          return collapse(testCase) ? "panel-collapse collapse" : "panel-collapse collapse in";
        })
        .attr("id", function (testCase) {
          return name + testCase.id;
        })
        .append("pre")
        .text(function (testCase) {
          return text(testCase);
        });
    };
  };

  my.renderTestresults = function (projectSelection) {
    var suiteResults = projectSelection.selectAll(".suiteResult").data(function (node) {
      return node.testResult.failedTests || [];
    }, function (test) {
      return test.name + "-" + test.className;
    });

    suiteResults.enter()
      .append("div")
      .attr("class", "suiteResult list-group")
      .append("div")
      .attr("class", "list-group-item suite")
      .html(function (test) {
        return "
" + test.name + "
";
      });

    var testResults = suiteResults.selectAll(".testResult").data(function (suite) {
      return suite.cases;
    }, function (testCase) {
      return testCase.name;
    });

    testResults.enter()
      .append("div")
      .attr("class", "input-group testResult")
      .html(function (testCase) {
        return '<input class="testCaseSelect" data-testCaseId="' + testCase.id + '" type="checkbox">';
      })
      .append("div")
      .attr("class", "list-group-item")
      .html(function (testCase) {
        return '
' +
          [
            '
',
            '', testCase.name, ' ',
            ' ',
            '', testCase.age, '',
            '
'].join("") +
          '
' +
          '
';
      })
      .call(appendTestCaseDetails("details", 'Details',
        function (testCase) {
          return testCase.errorDetails;
        },
        function (testCase) {
          return testCase.errorDetails.length > 1200;
        },
        function (testCase) {
          return testCase.errorDetails;
          //.substring(0, 1200).replace(/\[\d+, (\d+(, )?)*\]/, "");
        }
      ))
      .call(appendTestCaseDetails("stacktrace", 'Stacktrace',
        function (testCase) {
          return testCase.errorStackTrace;
        },
        function () {
          return true;
        },
        function (testCase) {
          return testCase.errorStackTrace;
          //.replace(/\[\d+, (\d+(, )?)*\]/, "");
        }
      ));

    testResults.select('.claim').call(my.formatClaim);

    var warnings = projectSelection.selectAll(".warning").data(function (node) {
      return node.warnings || [];
    });

    warnings.enter()
      .append("div")
      .attr("class", "warning")
      .append("div")
      .attr("class", "list-group-item")
      .html(function (warning) {
        return "
" + warning.fileName + "
";
      })
      .call(appendTestCaseDetails("warning", "Warning", function () {
        return true;
      }, function () {
        return false;
      }, function (warning) {
        return warning.message;
      }));

    $(function () {
      $('[data-toggle="tooltip"]').tooltip();
    });
  };

  my.renderLoop = function (eventSource, eventName, render) {
    var viewNeedsUpdate = true;
    $(eventSource).bind(eventName, function () {
      viewNeedsUpdate = true;
      setTimeout(function () {
        if (viewNeedsUpdate) {
          render();
          viewNeedsUpdate = false;
        }
      }, 20);
    });
    $(eventSource).trigger(eventName);
  };

  return my;
});<commit_msg>Link Name nur maximal 400 Zeichen<commit_after>define(['jquery', 'bootstrap'], function ($) {
  'use strict';
  var my = {};

  my.dateTimeFormat = {year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric'};

  my.formatClaim = function (el) {
    el.html(function (claimedObject) {
      var claim = claimedObject.claim;
      if (claim.claimed) {
        return ' ' + (claim.reason ? (' ' + claim.reason + '
 ') : '') +
          ' ' + claim.claimedBy + '' +
          ' ' + new Date(claim.claimDate).toLocaleString('de-DE', my.dateTimeFormat) + '';
      } else {
        return '';
      }
    });
  };

  var appendTestCaseDetails = function (name, description, present, collapse, text) {
    return function (hull) {
      hull
        .filter(present)
        .append("div").call(function (div) {
          div.append("h6")
            .append("a")
            .attr("data-toggle", "collapse")
            .attr("href", function (testCase) {
              return "#" + name + testCase.id;
            })
            .text(description)
            .append("span")
            .attr("class", "caret")
          ;
        })
        .append("div")
        .attr("class", function (testCase) {
          return collapse(testCase) ? "panel-collapse collapse" : "panel-collapse collapse in";
        })
        .attr("id", function (testCase) {
          return name + testCase.id;
        })
        .append("pre")
        .text(function (testCase) {
          return text(testCase);
        });
    };
  };

  my.renderTestresults = function (projectSelection) {
    var suiteResults = projectSelection.selectAll(".suiteResult").data(function (node) {
      return node.testResult.failedTests || [];
    }, function (test) {
      return test.name + "-" + test.className;
    });

    suiteResults.enter()
      .append("div")
      .attr("class", "suiteResult list-group")
      .append("div")
      .attr("class", "list-group-item suite")
      .html(function (test) {
        return "
" + test.name + "
";
      });

    var testResults = suiteResults.selectAll(".testResult").data(function (suite) {
      return suite.cases;
    }, function (testCase) {
      return testCase.name;
    });

    testResults.enter()
      .append("div")
      .attr("class", "input-group testResult")
      .html(function (testCase) {
        return '<input class="testCaseSelect" data-testCaseId="' + testCase.id + '" type="checkbox">';
      })
      .append("div")
      .attr("class", "list-group-item")
      .html(function (testCase) {
        return '
' +
          [
            '
',
            '', testCase.name.substring(0, 400), ' ',
            ' ',
            '', testCase.age, '',
            '
'].join("") +
          '
' +
          '
';
      })
      .call(appendTestCaseDetails("details", 'Details',
        function (testCase) {
          return testCase.errorDetails;
        },
        function (testCase) {
          return testCase.errorDetails.length > 1200;
        },
        function (testCase) {
          return testCase.errorDetails;
          //.substring(0, 1200).replace(/\[\d+, (\d+(, )?)*\]/, "");
        }
      ))
      .call(appendTestCaseDetails("stacktrace", 'Stacktrace',
        function (testCase) {
          return testCase.errorStackTrace;
        },
        function () {
          return true;
        },
        function (testCase) {
          return testCase.errorStackTrace;
          //.replace(/\[\d+, (\d+(, )?)*\]/, "");
        }
      ));

    testResults.select('.claim').call(my.formatClaim);

    var warnings = projectSelection.selectAll(".warning").data(function (node) {
      return node.warnings || [];
    });

    warnings.enter()
      .append("div")
      .attr("class", "warning")
      .append("div")
      .attr("class", "list-group-item")
      .html(function (warning) {
        return "
" + warning.fileName + "
";
      })
      .call(appendTestCaseDetails("warning", "Warning", function () {
        return true;
      }, function () {
        return false;
      }, function (warning) {
        return warning.message;
      }));

    $(function () {
      $('[data-toggle="tooltip"]').tooltip();
    });
  };

  my.renderLoop = function (eventSource, eventName, render) {
    var viewNeedsUpdate = true;
    $(eventSource).bind(eventName, function () {
      viewNeedsUpdate = true;
      setTimeout(function () {
        if (viewNeedsUpdate) {
          render();
          viewNeedsUpdate = false;
        }
      }, 20);
    });
    $(eventSource).trigger(eventName);
  };

  return my;
});<|endoftext|>


<commit_before>'use babel'

import Communication from 'sb-communication'
import {CompositeDisposable} from 'sb-event-kit'

class ProcessCommunication {
  constructor(process, debug) {
    if (typeof process.send !== 'function') {
      throw new Error('Invalid process specified')
    }

    this.process = process
    this.communication = new Communication(debug)
    this.subscriptions = new CompositeDisposable(this.communication)

    this.communication.onShouldSend(data => {
      this.process.send(data)
    })

    const callback = message => {
      this.communication.parseMessage(message)
    }
    this.process.addEventListener('message', callback)
    this.subscriptions.add({
      dispose: function() {
        process.removeListener('message', callback)
      }
    })
  }
  request(name, data = {}) {
    return this.communication.request(name, data)
  }

  onRequest(name, callback) {
    return this.communication.onRequest(name, callback)
  }

  kill() {
    this.process.kill()
  }
  disconnect() {
    this.process.disconnect()
  }
  dispose() {
    this.communication.dispose()
    this.kill()
  }
}

export {ProcessCommunication as Communication}
<commit_msg>:art: Enhance disposing logic<commit_after>'use babel'

import Communication from 'sb-communication'
import {CompositeDisposable} from 'sb-event-kit'

class ProcessCommunication {
  constructor(process, debug) {
    if (typeof process.send !== 'function') {
      throw new Error('Invalid process specified')
    }

    this.process = process
    this.communication = new Communication(debug)
    this.subscriptions = new CompositeDisposable(this.communication)

    this.communication.onShouldSend(data => {
      this.process.send(data)
    })

    const callback = message => {
      this.communication.parseMessage(message)
    }
    this.process.addEventListener('message', callback)
    this.subscriptions.add({
      dispose: function() {
        process.removeListener('message', callback)
      }
    })
  }
  request(name, data = {}) {
    return this.communication.request(name, data)
  }

  onRequest(name, callback) {
    return this.communication.onRequest(name, callback)
  }

  kill(sig) {
    this.process.kill(sig)
  }
  dispose() {
    this.subscriptions.dispose()
  }
}

export {ProcessCommunication as Communication}
<|endoftext|>


<commit_before>const Compiler = require('./compiler');
const defaults = require('./defaults');

/**
 * 编译模版
 * @param {string|Object} source   模板内容
 * @param {?Object}       options  编译选项
 * @return {function}
 */
const compile = (source, options = {}) => {

    if (typeof source === 'object') {
        options = source;
    } else {
        options.source = source;
    }

    // 合并默认配置
    options = defaults.$extend(options);
    source = options.source;

    // debug 模式
    if (options.debug) {
        options.cache = false;
        options.bail = false;
        options.minimize = false;
        options.compileDebug = true;
    }

    const onerror = options.onerror;
    const filename = options.filename;
    const cache = options.cache;
    const caches = options.caches;

    // 匹配缓存
    if (cache && filename) {
        const render = caches.get(filename);
        if (render) {
            return render;
        }
    }

    // 加载外部模板
    if (!source) {

        const target = options.resolveFilename(filename, options);

        try {
            source = options.loader(target, options);
            options.filename = target;
            options.source = source;
        } catch (e) {

            const error = {
                path: filename,
                name: 'CompileError',
                message: `template not found: ${e.message}`,
                stack: e.stack
            };

            if (options.bail) {
                throw error;
            } else {
                return onerror(error, options);
            }

        }

    }

    const compiler = new Compiler(options);

    const render = (data, blocks) => {

        try {
            return render.source(data, blocks);
        } catch (error) {

            // 运行时出错以调试模式重载
            if (!options.compileDebug) {
                options.cache = false;
                options.compileDebug = true;
                return compile(options)(data, blocks);
            }

            if (options.bail) {
                throw error;
            } else {
                return onerror(error, options)();
            }

        }
    };

    try {
        render.source = compiler.build();

        // 缓存编译成功的模板
        if (cache && filename) {
            caches.set(filename, render);
        }

    } catch (error) {
        if (options.bail) {
            throw error;
        } else {
            return onerror(error, options);
        }
    }

    render.toString = function() {
        return render.source.toString();
    };

    return render;
};

compile.Compiler = Compiler;

module.exports = compile;<commit_msg>优化 options.filename<commit_after>const Compiler = require('./compiler');
const defaults = require('./defaults');

/**
 * 编译模版
 * @param {string|Object} source   模板内容
 * @param {?Object}       options  编译选项
 * @return {function}
 */
const compile = (source, options = {}) => {

    if (typeof source === 'object') {
        options = source;
    } else {
        options.source = source;
    }

    // 合并默认配置
    options = defaults.$extend(options);
    source = options.source;

    // debug 模式
    if (options.debug) {
        options.cache = false;
        options.bail = false;
        options.minimize = false;
        options.compileDebug = true;
    }

    // 转换成绝对路径
    if (options.filename) {
        options.filename = options.resolveFilename(options.filename, options);
    }

    const onerror = options.onerror;
    const filename = options.filename;
    const cache = options.cache;
    const caches = options.caches;

    // 匹配缓存
    if (cache && filename) {
        const render = caches.get(filename);
        if (render) {
            return render;
        }
    }

    // 加载外部模板
    if (!source) {

        try {
            source = options.loader(filename, options);
            options.source = source;
        } catch (e) {

            const error = {
                path: filename,
                name: 'CompileError',
                message: `template not found: ${e.message}`,
                stack: e.stack
            };

            if (options.bail) {
                throw error;
            } else {
                return onerror(error, options);
            }

        }

    }

    const compiler = new Compiler(options);

    const render = (data, blocks) => {

        try {
            return render.source(data, blocks);
        } catch (error) {

            // 运行时出错以调试模式重载
            if (!options.compileDebug) {
                options.cache = false;
                options.compileDebug = true;
                return compile(options)(data, blocks);
            }

            if (options.bail) {
                throw error;
            } else {
                return onerror(error, options)();
            }

        }
    };

    try {
        render.source = compiler.build();

        // 缓存编译成功的模板
        if (cache && filename) {
            caches.set(filename, render);
        }

    } catch (error) {
        if (options.bail) {
            throw error;
        } else {
            return onerror(error, options);
        }
    }

    render.toString = function() {
        return render.source.toString();
    };

    return render;
};

compile.Compiler = Compiler;

module.exports = compile;<|endoftext|>