<commit_before>;(function(GGRC, can) {

  function Proxy(
      option_model_name, join_option_attr, join_model_name, join_object_attr,
      instance_join_attr) {
    return new GGRC.ListLoaders.ProxyListLoader(
        join_model_name, join_object_attr, join_option_attr,
        instance_join_attr, option_model_name);
  }

  function Direct(option_model_name, instance_join_attr) {
    return new GGRC.ListLoaders.DirectListLoader(option_model_name, instance_join_attr);
  }

  function Multi(sources) {
    return new GGRC.ListLoaders.MultiListLoader(sources);
  }

  function TypeFilter(source, model_name) {
    return new GGRC.ListLoaders.TypeFilteredListLoader(source, [model_name]);
  }

  function Cross(local_mapping, remote_mapping) {
    return new GGRC.ListLoaders.CrossListLoader(local_mapping, remote_mapping);
  }

  function create_mappings(definitions) {
    var mappings = {};

    // Recursively handle mixins
    function reify_mixins(definition) {
      var final_definition = {};
      if (definition._mixins) {
        can.each(definition._mixins, function(mixin) {
          if (typeof(mixin) === "string") {
            // If string, recursive lookup
            if (!definitions[mixin])
              console.debug("Undefined mixin: " + mixin, definitions);
            else
              can.extend(final_definition, reify_mixins(definitions[mixin]));
          } else if (can.isFunction(mixin)) {
            // If function, call with current definition state
            mixin(final_definition);
          } else {
            // Otherwise, assume object and extend
            can.extend(final_definition, mixin);
          }
        });
      }
      can.extend(final_definition, definition);
      delete final_definition._mixins;
      return final_definition;
    }

    can.each(definitions, function(definition, name) {
      // Only output the mappings if it's a model, e.g., uppercase first letter
      if (name[0] === name[0].toUpperCase())
        mappings[name] = reify_mixins(definition);
    });

    return mappings;
  }

  function extended_related(name) {
    return function(definition) {
      definition["related_" + name + "_via_sections"] = Cross("sections", "related_" + name);
      definition["related_" + name + "_via_extended_controls"] = Cross("extended_related_controls", "related_" + name);
      definition["related_" + name + "_via_extended_objectives"] = Cross("extended_related_objectives", "related_" + name);

      definition["extended_related_" + name] = Multi([
            "related_" + name + "_via_sections"
          , "related_" + name + "_via_extended_controls"
          , "related_" + name + "_via_extended_objectives"
          , "related_" + name
          ]);
    };
  }

  GGRC.Mappings = create_mappings({
      base: {
      }

    // Governance
    , Control: {
        _mixins: ["personable", "documentable"] //controllable
      , related_objects: Proxy(
          null, "controllable", "ObjectControl", "control", "object_controls") //control_objects
      , related_data_assets: TypeFilter("related_objects", "DataAsset")
      , related_facilities:  TypeFilter("related_objects", "Facility")
      , related_markets:     TypeFilter("related_objects", "Market")
      , related_org_groups:  TypeFilter("related_objects", "OrgGroup")
      , related_processes:   TypeFilter("related_objects", "Process")
      , related_products:    TypeFilter("related_objects", "Product")
      , related_projects:    TypeFilter("related_objects", "Project")
      , related_systems:     TypeFilter("related_objects", "System")
      , programs: Proxy(
          "Program", "program", "ProgramControl", "control", "program_controls")
      //, controls: Proxy(
      //    "Control", "control", "ObjectControl", "controllable", "object_controls")
      , objectives: Proxy(
          "Objective", "objective", "ObjectiveControl", "control", "objective_controls")
      , sections: Proxy(
          "Section", "section", "ControlSection", "control", "control_sections")
      }
    , Objective: {
        _mixins: ["personable", "documentable"] //objectiveable
      , related_objects: Proxy(
          null, "objectiveable", "ObjectObjective", "objective", "objective_objects")
      , related_data_assets: TypeFilter("related_objects", "DataAsset")
      , related_facilities:  TypeFilter("related_objects", "Facility")
      , related_markets:     TypeFilter("related_objects", "Market")
      , related_org_groups:  TypeFilter("related_objects", "OrgGroup")
      , related_processes:   TypeFilter("related_objects", "Process")
      , related_products:    TypeFilter("related_objects", "Product")
      , related_projects:    TypeFilter("related_objects", "Project")
      , related_systems:     TypeFilter("related_objects", "System")
      , objectives: Proxy(
          "Objective", "objective", "ObjectObjective", "objectiveable", "object_objectives")
      , controls: Proxy(
          "Control", "control", "ObjectiveControl", "objective", "objective_controls")
      , sections: Proxy(
          "Section", "section", "SectionObjective", "objective", "section_objectives")
      }
    , Section: {
        _mixins: ["personable", "documentable"] //sectionable
      , related_objects: Proxy(
          null, "sectionable", "ObjectSection", "section", "object_sections") //section_objects
      , related_data_assets: TypeFilter("related_objects", "DataAsset")
      , related_facilities:  TypeFilter("related_objects", "Facility")
      , related_markets:     TypeFilter("related_objects", "Market")
      , related_org_groups:  TypeFilter("related_objects", "OrgGroup")
      , related_processes:   TypeFilter("related_objects", "Process")
      , related_products:    TypeFilter("related_objects", "Product")
      , related_projects:    TypeFilter("related_objects", "Project")
      , related_systems:     TypeFilter("related_objects", "System")
      //, sections: Proxy(
      //    "Section", "section", "ObjectSection", "sectionable", "object_sections")
      , objectives: Proxy(
          "Objective", "objective", "SectionObjective", "section", "section_objectives")
      , controls: Proxy(
          "Control", "control", "ControlSection", "section", "control_sections")
      }

    , controllable: {
        controls: Proxy(
          "Control", "control", "ObjectControl", "controllable", "object_controls")
      }

    , objectiveable: {
        objectives: Proxy(
          "Objective", "objective", "ObjectObjective", "objectiveable", "object_objectives")
      }

    , sectionable: {
        sections: Proxy(
          "Section", "section", "ObjectSection", "sectionable", "object_sections")
      }

    , personable: {
        people: Proxy(
          "Person", "person", "ObjectPerson", "personable", "object_people")
      }

    , documentable: {
        documents: Proxy(
          "Document", "document", "ObjectDocument", "documentable", "object_documents")
      }

    , related_object: {
        related_objects_as_source: Proxy(
          null, "destination", "Relationship", "source", "related_destinations")
      , related_objects_as_destination: Proxy(
          null, "source", "Relationship", "destination", "related_sources")
      , related_objects: Multi(["related_objects_as_source", "related_objects_as_destination"])
      , related_data_assets: TypeFilter("related_objects", "DataAsset")
      , related_facilities:  TypeFilter("related_objects", "Facility")
      , related_markets:     TypeFilter("related_objects", "Market")
      , related_org_groups:  TypeFilter("related_objects", "OrgGroup")
      , related_processes:   TypeFilter("related_objects", "Process")
      , related_products:    TypeFilter("related_objects", "Product")
      , related_projects:    TypeFilter("related_objects", "Project")
      , related_systems:     TypeFilter("related_objects", "System")
      }

    // Program
    , Program: {
        _mixins: [
            "related_object", "personable", "documentable", "objectiveable"
          , extended_related("data_assets")
          , extended_related("facilities")
          , extended_related("markets")
          , extended_related("org_groups")
          , extended_related("processes")
          , extended_related("products")
          , extended_related("projects")
          , extended_related("systems")
          ]
      , controls: Proxy(
          "Control", "control", "ProgramControl", "program", "program_controls")
      /*, objectives: Proxy(
          "Objective", "objective", "ObjectObjective", "objectiveable", "object_objectives")*/
      , directives: Proxy(
          null, "directive", "ProgramDirective", "program", "program_directives")
      , contracts: TypeFilter("directives", "Contract")
      , policies: TypeFilter("directives", "Policy")
      , regulations: TypeFilter("directives", "Regulation")

      , sections_via_directives: Cross("directives", "sections")
      , sections_via_controls: Cross("controls", "sections")
      , sections: Multi(["sections_via_controls", "sections_via_directives"])

      , controls_via_sections: Cross("sections", "controls")
      , objectives_via_sections: Cross("sections", "objectives")
      , extended_related_objectives: Multi(["objectives_via_sections", "objectives"])
      , controls_via_extended_objectives: Cross("extended_related_objectives", "controls")
      , extended_related_controls: Multi([
            "controls_via_extended_objectives"
          , "controls_via_sections"
          , "controls"])

      , related_documents_via_sections: Cross("sections", "documents")
      , related_documents_via_extended_controls: Cross("extended_related_controls", "documents")
      , related_documents_via_extended_objectives: Cross("extended_related_objectives", "documents")
      , extended_related_documents:
          Multi([
              "related_documents_via_extended_controls"
            , "related_documents_via_extended_objectives"
            , "related_documents_via_sections"
            ])

      , related_people_via_sections: Cross("sections", "people")
      , related_people_via_extended_controls: Cross("extended_related_controls", "people")
      , related_people_via_extended_objectives: Cross("extended_related_objectives", "people")
      , extended_related_people:
          Multi([
              "related_people_via_extended_controls"
            , "related_people_via_extended_objectives"
            , "related_people_via_sections"
            ])

      , related_objects_via_sections:
          Cross("sections", "related_objects")
      , related_objects_via_extended_controls:
          Cross("extended_related_controls", "related_objects")
      , related_objects_via_extended_objectives:
          Cross("extended_related_objectives", "related_objects")
      , extended_related_objects:
          Multi([
              "related_objects_via_extended_controls"
            , "related_objects_via_extended_objectives"
            , "related_objects_via_sections"
            , "related_objects"
            ])
      /*, extended_related_data_assets: TypeFilter("extended_related_objects", "DataAsset")
      , extended_related_facilities:  TypeFilter("extended_related_objects", "Facility")
      , extended_related_markets:     TypeFilter("extended_related_objects", "Market")
      , extended_related_org_groups:  TypeFilter("extended_related_objects", "OrgGroup")
      , extended_related_processes:   TypeFilter("extended_related_objects", "Process")
      , extended_related_products:    TypeFilter("extended_related_objects", "Product")
      , extended_related_projects:    TypeFilter("extended_related_objects", "Project")
      , extended_related_systems:     TypeFilter("extended_related_objects", "System")
      */
      }

    , directive_object: {
        _mixins: [
          "related_object", "personable", "documentable"//, "objectiveable"
          , extended_related("data_assets")
          , extended_related("facilities")
          , extended_related("markets")
          , extended_related("org_groups")
          , extended_related("processes")
          , extended_related("products")
          , extended_related("projects")
          , extended_related("systems")
          ]
      , sections: Direct("Section", "directive")
      , controls: Direct("Control", "directive")

      , controls_via_sections: Cross("sections", "controls")
      , objectives_via_sections: Cross("sections", "objectives")
      , extended_related_objectives: Multi(["objectives_via_sections"])//, "objectives"])
      , controls_via_extended_objectives: Cross("extended_related_objectives", "controls")
      , extended_related_controls: Multi([
            "controls_via_extended_objectives"
          , "controls_via_sections"
          , "controls"])

      , related_objects_via_sections: Cross("sections", "related_objects")

      , related_documents_via_sections: Cross("sections", "documents")
      , related_documents_via_extended_controls: Cross("extended_related_controls", "documents")
      , related_documents_via_extended_objectives: Cross("extended_related_objectives", "documents")
      , extended_related_documents:
          Multi([
              "documents"
            , "related_documents_via_extended_controls"
            , "related_documents_via_extended_objectives"
            , "related_documents_via_sections"
            ])

      , related_people_via_sections: Cross("sections", "people")
      , related_people_via_extended_controls: Cross("extended_related_controls", "people")
      , related_people_via_extended_objectives: Cross("extended_related_objectives", "people")
      , extended_related_people:
          Multi([
              "people"
            , "related_people_via_extended_controls"
            , "related_people_via_extended_objectives"
            , "related_people_via_sections"
            ])
      }

    // Directives
    , Regulation: {
        _mixins: ["directive_object"]
      }
    , Contract: {
        _mixins: ["directive_object"]
      }
    , Policy: {
        _mixins: ["directive_object"]
      }

    // Business objects
    , business_object: {
        _mixins: [
            "related_object", "personable", "documentable"
          , "controllable", "objectiveable", "sectionable"
          ]
      }

    , DataAsset: {
        _mixins: ["business_object"]
      }
    , Facility: {
        _mixins: ["business_object"]
      }
    , Market: {
        _mixins: ["business_object"]
      }
    , OrgGroup: {
        _mixins: ["business_object"]
      }
    , Product: {
        _mixins: ["business_object"]
      }
    , Project: {
        _mixins: ["business_object"]
      }
    , System: {
        _mixins: ["business_object"]
      }
    , Process: {
        _mixins: ["business_object"]
      }
  });
})(GGRC, can);
<commit_msg>Fix display of mappings of People/References to Program<commit_after>;(function(GGRC, can) {

  function Proxy(
      option_model_name, join_option_attr, join_model_name, join_object_attr,
      instance_join_attr) {
    return new GGRC.ListLoaders.ProxyListLoader(
        join_model_name, join_object_attr, join_option_attr,
        instance_join_attr, option_model_name);
  }

  function Direct(option_model_name, instance_join_attr) {
    return new GGRC.ListLoaders.DirectListLoader(option_model_name, instance_join_attr);
  }

  function Multi(sources) {
    return new GGRC.ListLoaders.MultiListLoader(sources);
  }

  function TypeFilter(source, model_name) {
    return new GGRC.ListLoaders.TypeFilteredListLoader(source, [model_name]);
  }

  function Cross(local_mapping, remote_mapping) {
    return new GGRC.ListLoaders.CrossListLoader(local_mapping, remote_mapping);
  }

  function create_mappings(definitions) {
    var mappings = {};

    // Recursively handle mixins
    function reify_mixins(definition) {
      var final_definition = {};
      if (definition._mixins) {
        can.each(definition._mixins, function(mixin) {
          if (typeof(mixin) === "string") {
            // If string, recursive lookup
            if (!definitions[mixin])
              console.debug("Undefined mixin: " + mixin, definitions);
            else
              can.extend(final_definition, reify_mixins(definitions[mixin]));
          } else if (can.isFunction(mixin)) {
            // If function, call with current definition state
            mixin(final_definition);
          } else {
            // Otherwise, assume object and extend
            can.extend(final_definition, mixin);
          }
        });
      }
      can.extend(final_definition, definition);
      delete final_definition._mixins;
      return final_definition;
    }

    can.each(definitions, function(definition, name) {
      // Only output the mappings if it's a model, e.g., uppercase first letter
      if (name[0] === name[0].toUpperCase())
        mappings[name] = reify_mixins(definition);
    });

    return mappings;
  }

  function extended_related(name) {
    return function(definition) {
      definition["related_" + name + "_via_sections"] = Cross("sections", "related_" + name);
      definition["related_" + name + "_via_extended_controls"] = Cross("extended_related_controls", "related_" + name);
      definition["related_" + name + "_via_extended_objectives"] = Cross("extended_related_objectives", "related_" + name);

      definition["extended_related_" + name] = Multi([
            "related_" + name + "_via_sections"
          , "related_" + name + "_via_extended_controls"
          , "related_" + name + "_via_extended_objectives"
          , "related_" + name
          ]);
    };
  }

  GGRC.Mappings = create_mappings({
      base: {
      }

    // Governance
    , Control: {
        _mixins: ["personable", "documentable"] //controllable
      , related_objects: Proxy(
          null, "controllable", "ObjectControl", "control", "object_controls") //control_objects
      , related_data_assets: TypeFilter("related_objects", "DataAsset")
      , related_facilities:  TypeFilter("related_objects", "Facility")
      , related_markets:     TypeFilter("related_objects", "Market")
      , related_org_groups:  TypeFilter("related_objects", "OrgGroup")
      , related_processes:   TypeFilter("related_objects", "Process")
      , related_products:    TypeFilter("related_objects", "Product")
      , related_projects:    TypeFilter("related_objects", "Project")
      , related_systems:     TypeFilter("related_objects", "System")
      , programs: Proxy(
          "Program", "program", "ProgramControl", "control", "program_controls")
      //, controls: Proxy(
      //    "Control", "control", "ObjectControl", "controllable", "object_controls")
      , objectives: Proxy(
          "Objective", "objective", "ObjectiveControl", "control", "objective_controls")
      , sections: Proxy(
          "Section", "section", "ControlSection", "control", "control_sections")
      }
    , Objective: {
        _mixins: ["personable", "documentable"] //objectiveable
      , related_objects: Proxy(
          null, "objectiveable", "ObjectObjective", "objective", "objective_objects")
      , related_data_assets: TypeFilter("related_objects", "DataAsset")
      , related_facilities:  TypeFilter("related_objects", "Facility")
      , related_markets:     TypeFilter("related_objects", "Market")
      , related_org_groups:  TypeFilter("related_objects", "OrgGroup")
      , related_processes:   TypeFilter("related_objects", "Process")
      , related_products:    TypeFilter("related_objects", "Product")
      , related_projects:    TypeFilter("related_objects", "Project")
      , related_systems:     TypeFilter("related_objects", "System")
      , objectives: Proxy(
          "Objective", "objective", "ObjectObjective", "objectiveable", "object_objectives")
      , controls: Proxy(
          "Control", "control", "ObjectiveControl", "objective", "objective_controls")
      , sections: Proxy(
          "Section", "section", "SectionObjective", "objective", "section_objectives")
      }
    , Section: {
        _mixins: ["personable", "documentable"] //sectionable
      , related_objects: Proxy(
          null, "sectionable", "ObjectSection", "section", "object_sections") //section_objects
      , related_data_assets: TypeFilter("related_objects", "DataAsset")
      , related_facilities:  TypeFilter("related_objects", "Facility")
      , related_markets:     TypeFilter("related_objects", "Market")
      , related_org_groups:  TypeFilter("related_objects", "OrgGroup")
      , related_processes:   TypeFilter("related_objects", "Process")
      , related_products:    TypeFilter("related_objects", "Product")
      , related_projects:    TypeFilter("related_objects", "Project")
      , related_systems:     TypeFilter("related_objects", "System")
      //, sections: Proxy(
      //    "Section", "section", "ObjectSection", "sectionable", "object_sections")
      , objectives: Proxy(
          "Objective", "objective", "SectionObjective", "section", "section_objectives")
      , controls: Proxy(
          "Control", "control", "ControlSection", "section", "control_sections")
      }

    , controllable: {
        controls: Proxy(
          "Control", "control", "ObjectControl", "controllable", "object_controls")
      }

    , objectiveable: {
        objectives: Proxy(
          "Objective", "objective", "ObjectObjective", "objectiveable", "object_objectives")
      }

    , sectionable: {
        sections: Proxy(
          "Section", "section", "ObjectSection", "sectionable", "object_sections")
      }

    , personable: {
        people: Proxy(
          "Person", "person", "ObjectPerson", "personable", "object_people")
      }

    , documentable: {
        documents: Proxy(
          "Document", "document", "ObjectDocument", "documentable", "object_documents")
      }

    , related_object: {
        related_objects_as_source: Proxy(
          null, "destination", "Relationship", "source", "related_destinations")
      , related_objects_as_destination: Proxy(
          null, "source", "Relationship", "destination", "related_sources")
      , related_objects: Multi(["related_objects_as_source", "related_objects_as_destination"])
      , related_data_assets: TypeFilter("related_objects", "DataAsset")
      , related_facilities:  TypeFilter("related_objects", "Facility")
      , related_markets:     TypeFilter("related_objects", "Market")
      , related_org_groups:  TypeFilter("related_objects", "OrgGroup")
      , related_processes:   TypeFilter("related_objects", "Process")
      , related_products:    TypeFilter("related_objects", "Product")
      , related_projects:    TypeFilter("related_objects", "Project")
      , related_systems:     TypeFilter("related_objects", "System")
      }

    // Program
    , Program: {
        _mixins: [
            "related_object", "personable", "documentable", "objectiveable"
          , extended_related("data_assets")
          , extended_related("facilities")
          , extended_related("markets")
          , extended_related("org_groups")
          , extended_related("processes")
          , extended_related("products")
          , extended_related("projects")
          , extended_related("systems")
          ]
      , controls: Proxy(
          "Control", "control", "ProgramControl", "program", "program_controls")
      /*, objectives: Proxy(
          "Objective", "objective", "ObjectObjective", "objectiveable", "object_objectives")*/
      , directives: Proxy(
          null, "directive", "ProgramDirective", "program", "program_directives")
      , contracts: TypeFilter("directives", "Contract")
      , policies: TypeFilter("directives", "Policy")
      , regulations: TypeFilter("directives", "Regulation")

      , sections_via_directives: Cross("directives", "sections")
      , sections_via_controls: Cross("controls", "sections")
      , sections: Multi(["sections_via_controls", "sections_via_directives"])

      , controls_via_sections: Cross("sections", "controls")
      , objectives_via_sections: Cross("sections", "objectives")
      , extended_related_objectives: Multi(["objectives_via_sections", "objectives"])
      , controls_via_extended_objectives: Cross("extended_related_objectives", "controls")
      , extended_related_controls: Multi([
            "controls_via_extended_objectives"
          , "controls_via_sections"
          , "controls"])

      , related_documents_via_sections: Cross("sections", "documents")
      , related_documents_via_extended_controls: Cross("extended_related_controls", "documents")
      , related_documents_via_extended_objectives: Cross("extended_related_objectives", "documents")
      , extended_related_documents:
          Multi([
              "documents"
            , "related_documents_via_extended_controls"
            , "related_documents_via_extended_objectives"
            , "related_documents_via_sections"
            ])

      , related_people_via_sections: Cross("sections", "people")
      , related_people_via_extended_controls: Cross("extended_related_controls", "people")
      , related_people_via_extended_objectives: Cross("extended_related_objectives", "people")
      , extended_related_people:
          Multi([
              "people"
            , "related_people_via_extended_controls"
            , "related_people_via_extended_objectives"
            , "related_people_via_sections"
            ])

      , related_objects_via_sections:
          Cross("sections", "related_objects")
      , related_objects_via_extended_controls:
          Cross("extended_related_controls", "related_objects")
      , related_objects_via_extended_objectives:
          Cross("extended_related_objectives", "related_objects")
      , extended_related_objects:
          Multi([
              "related_objects_via_extended_controls"
            , "related_objects_via_extended_objectives"
            , "related_objects_via_sections"
            , "related_objects"
            ])
      /*, extended_related_data_assets: TypeFilter("extended_related_objects", "DataAsset")
      , extended_related_facilities:  TypeFilter("extended_related_objects", "Facility")
      , extended_related_markets:     TypeFilter("extended_related_objects", "Market")
      , extended_related_org_groups:  TypeFilter("extended_related_objects", "OrgGroup")
      , extended_related_processes:   TypeFilter("extended_related_objects", "Process")
      , extended_related_products:    TypeFilter("extended_related_objects", "Product")
      , extended_related_projects:    TypeFilter("extended_related_objects", "Project")
      , extended_related_systems:     TypeFilter("extended_related_objects", "System")
      */
      }

    , directive_object: {
        _mixins: [
          "related_object", "personable", "documentable"//, "objectiveable"
          , extended_related("data_assets")
          , extended_related("facilities")
          , extended_related("markets")
          , extended_related("org_groups")
          , extended_related("processes")
          , extended_related("products")
          , extended_related("projects")
          , extended_related("systems")
          ]
      , sections: Direct("Section", "directive")
      , controls: Direct("Control", "directive")

      , controls_via_sections: Cross("sections", "controls")
      , objectives_via_sections: Cross("sections", "objectives")
      , extended_related_objectives: Multi(["objectives_via_sections"])//, "objectives"])
      , controls_via_extended_objectives: Cross("extended_related_objectives", "controls")
      , extended_related_controls: Multi([
            "controls_via_extended_objectives"
          , "controls_via_sections"
          , "controls"])

      , related_objects_via_sections: Cross("sections", "related_objects")

      , related_documents_via_sections: Cross("sections", "documents")
      , related_documents_via_extended_controls: Cross("extended_related_controls", "documents")
      , related_documents_via_extended_objectives: Cross("extended_related_objectives", "documents")
      , extended_related_documents:
          Multi([
              "documents"
            , "related_documents_via_extended_controls"
            , "related_documents_via_extended_objectives"
            , "related_documents_via_sections"
            ])

      , related_people_via_sections: Cross("sections", "people")
      , related_people_via_extended_controls: Cross("extended_related_controls", "people")
      , related_people_via_extended_objectives: Cross("extended_related_objectives", "people")
      , extended_related_people:
          Multi([
              "people"
            , "related_people_via_extended_controls"
            , "related_people_via_extended_objectives"
            , "related_people_via_sections"
            ])
      }

    // Directives
    , Regulation: {
        _mixins: ["directive_object"]
      }
    , Contract: {
        _mixins: ["directive_object"]
      }
    , Policy: {
        _mixins: ["directive_object"]
      }

    // Business objects
    , business_object: {
        _mixins: [
            "related_object", "personable", "documentable"
          , "controllable", "objectiveable", "sectionable"
          ]
      }

    , DataAsset: {
        _mixins: ["business_object"]
      }
    , Facility: {
        _mixins: ["business_object"]
      }
    , Market: {
        _mixins: ["business_object"]
      }
    , OrgGroup: {
        _mixins: ["business_object"]
      }
    , Product: {
        _mixins: ["business_object"]
      }
    , Project: {
        _mixins: ["business_object"]
      }
    , System: {
        _mixins: ["business_object"]
      }
    , Process: {
        _mixins: ["business_object"]
      }
  });
})(GGRC, can);
<|endoftext|>


<commit_before>
import React from 'react'
import classnames from 'classnames'

const Textfield = ({
  autoFocus,
  defaultValue,
  disabled,
  error,
  icon,
  label,
  name,
  onChange,
  readOnly,
  type,
  value
}) => {
  var empty = value === ''
  return (

        {
          icon
          ?
{icon}

          : null
        }

          <input
            autoFocus={autoFocus}
            className={classnames('Textfield-input', {
              'Textfield-input--error': error,
              'is-not-empty': !empty
            })}
            defaultValue={defaultValue}
            disabled={disabled}
            name={name}
            onChange={onChange}
            readOnly={readOnly}
            type={type}
            value={value}
          />

            {label}

          {error
            ? {error}
            : null
          }

  )
}

Textfield.propTypes = {
  autoFocus: React.PropTypes.bool,
  disabled: React.PropTypes.bool,
  error: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.bool
  ]),
  icon: React.PropTypes.element,
  label: React.PropTypes.string,
  name: React.PropTypes.string,
  onChange: React.PropTypes.func,
  readOnly: React.PropTypes.bool,
  type: React.PropTypes.oneOf(['text', 'password', 'email', 'search', 'tel', 'url']),
  value: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.number
  ]),
  defaultValue: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.number
  ])
}

Textfield.defaultProps = {
  autoFocus: false,
  disabled: false,
  readOnly: false,
  type: 'text'
}

export default Textfield
<commit_msg>add number to allowed input types<commit_after>
import React from 'react'
import classnames from 'classnames'

const Textfield = ({
  autoFocus,
  defaultValue,
  disabled,
  error,
  icon,
  label,
  name,
  onChange,
  readOnly,
  type,
  value
}) => {
  var empty = value === ''
  return (

        {
          icon
          ?
{icon}

          : null
        }

          <input
            autoFocus={autoFocus}
            className={classnames('Textfield-input', {
              'Textfield-input--error': error,
              'is-not-empty': !empty
            })}
            defaultValue={defaultValue}
            disabled={disabled}
            name={name}
            onChange={onChange}
            readOnly={readOnly}
            type={type}
            value={value}
          />

            {label}

          {error
            ? {error}
            : null
          }

  )
}

Textfield.propTypes = {
  autoFocus: React.PropTypes.bool,
  disabled: React.PropTypes.bool,
  error: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.bool
  ]),
  icon: React.PropTypes.element,
  label: React.PropTypes.string,
  name: React.PropTypes.string,
  onChange: React.PropTypes.func,
  readOnly: React.PropTypes.bool,
  type: React.PropTypes.oneOf(['text', 'password', 'email', 'search', 'tel', 'url', 'number']),
  value: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.number
  ]),
  defaultValue: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.number
  ])
}

Textfield.defaultProps = {
  autoFocus: false,
  disabled: false,
  readOnly: false,
  type: 'text'
}

export default Textfield
<|endoftext|>


<commit_before>function roundNumber(num, dec) {
	var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
	return result;
}

$(document).ready(function() {
	$("#con_con").focus();

	$(".button").click(function() {
		var con_con = $("input#con_con").val();
		var con_sam = $("input#con_sam").val();
		var test_con = $("input#test_con").val();
		var test_sam = $("input#test_sam").val();
		var fx = $("input#fx").val();
		var dataString = 'conversions_control='+ con_con + '&samples_control=' + con_sam + '&conversions_experiment='+ test_con + '&samples_experiment=' + test_sam + '&function=' + fx;

		$.getJSON("api?" + dataString, function(stat_results){
			//clear g field
			$(".column").html("");

			//check for errors
			if(stat_results.error){
				return false;
			}

			//add text input with query args, then autofocus it
			var permalinkString = dataString.replace("conversions_control","cc").replace("samples_control","sc").replace("conversions_experiment","ce").replace("samples_experiment","se").replace("function","fx");
			$('<input class="permalink" value="http://'+location.host+location.pathname+'?'+permalinkString+'&permalink=true" type="text">').prependTo("#action").focus();
				$("input[type=text].permalink").focus(function(){
					$(this).select();
				})
				.mouseup(function(e){
					e.preventDefault();
				});

			//insert confidence charts
			var control_confidence = "

"+roundNumber(stat_results.confidence.results.control.low * 100,1)+" - "+roundNumber(stat_results.confidence.results.control.high * 100,1)+"%

Control performance

";
			var experiment_confidence = "

"+roundNumber(stat_results.confidence.results.experiment.low * 100,1)+" - "+roundNumber(stat_results.confidence.results.experiment.high * 100,1)+"%

Test performance

";

			$(control_confidence + experiment_confidence).appendTo(".column.left");

			//insert significance and improvement charts
			var significance = "

"+roundNumber(stat_results.significance.results.experiment * 100,1)+"%

Chance of outperformance

";
			var improvement = "

"+roundNumber(stat_results.improvement.results.low * 100,1)+" - "+roundNumber(stat_results.improvement.results.high * 100,1)+"%

Likely improvement

";

			$(significance + improvement).appendTo(".column.right")
		});

		return false;
	});

	//get results on permalink pages
	function getParameter(paramName) {
		var searchString = window.location.search.substring(1),
			i, val, params = searchString.split("&");

		for (i=0;i<params.length;i++) {
			val = params[i].split("=");
			if (val[0] == paramName) {
				return unescape(val[1]);
			}
		}
		return null;
	}

	if(getParameter("permalink") == "true"){
		$("input#con_con").val(getParameter("cc"));
		$("input#con_sam").val(getParameter("sc"));
		$("input#test_con").val(getParameter("ce"));
		$("input#test_sam").val(getParameter("se"));
		$(".button").click();
	}
});
<commit_msg>Move API requests into their own JS function so we don't need to fake button clicks<commit_after>function roundNumber(num, dec) {
	var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
	return result;
}

function submitData(con_con, con_sam, test_con, test_sam, fx) {
	var dataString = 'conversions_control='+ con_con + '&samples_control=' + con_sam + '&conversions_experiment='+ test_con + '&samples_experiment=' + test_sam + '&function=' + fx;

	$.getJSON("api?" + dataString, function(stat_results){
		//clear g field
		$(".column").html("");

		//check for errors
		if(stat_results.error){
			return false;
		}

		//add text input with query args, then autofocus it
		var permalinkString = dataString.replace("conversions_control","cc").replace("samples_control","sc").replace("conversions_experiment","ce").replace("samples_experiment","se").replace("function","fx");
		$('<input class="permalink" value="http://'+location.host+location.pathname+'?'+permalinkString+'&permalink=true" type="text">').prependTo("#action").focus();
			$("input[type=text].permalink").focus(function(){
				$(this).select();
			})
			.mouseup(function(e){
				e.preventDefault();
			});

		//insert confidence charts
		var control_confidence = "

"+roundNumber(stat_results.confidence.results.control.low * 100,1)+" - "+roundNumber(stat_results.confidence.results.control.high * 100,1)+"%

Control performance

";
		var experiment_confidence = "

"+roundNumber(stat_results.confidence.results.experiment.low * 100,1)+" - "+roundNumber(stat_results.confidence.results.experiment.high * 100,1)+"%

Test performance

";

		$(control_confidence + experiment_confidence).appendTo(".column.left");

		//insert significance and improvement charts
		var significance = "

"+roundNumber(stat_results.significance.results.experiment * 100,1)+"%

Chance of outperformance

";
		var improvement = "

"+roundNumber(stat_results.improvement.results.low * 100,1)+" - "+roundNumber(stat_results.improvement.results.high * 100,1)+"%

Likely improvement

";

		$(significance + improvement).appendTo(".column.right");
	});

	return false;
}

$(function() {
	$("#con_con").focus();

	$("form").on('submit', function(event){
		event.preventDefault();
		submitData(
			$("input#con_con").val(),
			$("input#con_sam").val(),
			$("input#test_con").val(),
			$("input#test_sam").val(),
			$("input#fx").val()
		);
	});

	//get results on permalink pages
	function getParameter(paramName) {
		var searchString = window.location.search.substring(1),
			i, val, params = searchString.split("&");

		for (i=0;i<params.length;i++) {
			val = params[i].split("=");
			if (val[0] == paramName) {
				return unescape(val[1]);
			}
		}
		return null;
	}

	if(getParameter("permalink") == "true"){
		$("input#con_con").val(getParameter("cc"));
		$("input#con_sam").val(getParameter("sc"));
		$("input#test_con").val(getParameter("ce"));
		$("input#test_sam").val(getParameter("se"));
		submitData(
			getParameter("cc"),
			getParameter("sc"),
			getParameter("ce"),
			getParameter("se"),
			getParameter("fx")
		);
	}
});
<|endoftext|>


<commit_before>angular
.module('app')
.controller('TrainingController', TrainingController)

function TrainingController($scope, $rootScope, $interval, $http, Rasa_Status, Agent, Intents, Expressions, ExpressionParameters, Rasa_Config) {
  var exportData;
  var statuscheck = $interval(getRasaStatus, 5000);
  $scope.generateError = "";
  $scope.trainings_under_this_process = 0;

  getRasaStatus();

  $scope.$on("$destroy", function(){
    $interval.cancel(statuscheck);
  });

  Agent.query(function(data) {
    $scope.agentList = data;
  });

  $scope.train = function() {
    var agentname = objectFindByKey($scope.agentList, 'agent_id', $scope.agent.agent_id).agent_name;

    var id = new XDate().toString('yyyyMMdd-HHmmss');
    $http.post(rasa_api_endpoint + "/train?name=" + agentname + "_" + id, JSON.stringify(exportData));
    //Minimize training data
    $scope.exportdata = {};
  }

  $scope.savetofile = function() {
      var data = new Blob([JSON.stringify($scope.exportdata, null, 2)], {type: 'text/plain'});

      var a = document.getElementById("a");
      a.download = "trainingdata.txt";
      a.href = URL.createObjectURL(data);
      a.click();
  }

  $scope.getData = function(agent_id) {
    //Get Intents, Expressions, Parameters/Entities, Synonyms
    var intent_i;
    var expression_i;
    var parameter_i;
    var intents;
    var expressions;
    var params;
    var synonyms;

    $http({method: 'GET', url: api_endpoint_v2 + "/agents/" + agent_id + "/intents"}).
    then(function(data) {
      intents = data.data;
      var intentIds = intents.map(function(item) { return item['intent_id']; }).toString();
      $http({method: 'GET', url: api_endpoint_v2 + "/intent_expressions?intent_ids=" + intentIds }).
      then(function(data) {
        expressions = data.data;
        var expressionIds = expressions.map(function(item) { return item['expression_id']; }).toString();
        $http({method: 'GET', url: api_endpoint_v2 + "/expression_parameters?expression_ids=" + expressionIds}).
        then(function(data) {
          params = data.data;
          var entityIds = params.map(function(item) { return item['entity_id']; }).toString();
          $http({method: 'GET', url: api_endpoint_v2 + '/entity_synonym_variants?entity_ids=' + entityIds}).
          then(function(data) {
            synonyms = data.data;
            generateData(intents, expressions, params, synonyms)
          }, function(error) {
            console.log(error);
          });
        }, function(error) {
          console.log(error);
        });
      }, function(error) {
        console.log(error);
      });
    }, function(error) {
      console.log(error);
    });
  }

  function generateData(intents, expressions, params, synonyms) {
    var tmpData = {};
    var tmpIntent = {};
    var tmpExpression = {};
    var tmpParam = {};
    tmpData.rasa_nlu_data = {}
    tmpData.rasa_nlu_data.common_examples = [];

    for (intent_i = 0; intent_i <= intents.length - 1; intent_i++) {
      var expressionList = expressions.filter(expression => expression.intent_id === intents[intent_i].intent_id);
      if (expressionList !== undefined) {
        for (expression_i = 0; expression_i <= expressionList.length - 1; expression_i++) {
          tmpIntent = {};
          tmpExpression = {};

          tmpIntent.intent = intents[intent_i].intent_name;
          tmpIntent.text = expressionList[expression_i].expression_text;
          tmpIntent.entities = [];
          tmpIntent.expression_id = expressionList[expression_i].expression_id;

          var parameterList = params.filter(param => param.expression_id === expressionList[expression_i].expression_id);
          var entities = [];
          if (parameterList !== undefined) {
            for (parameter_i = 0; parameter_i <= parameterList.length - 1; parameter_i++) {
              tmpParam = {};
              tmpParam.start = parameterList[parameter_i].parameter_start;
              tmpParam.end = parameterList[parameter_i].parameter_end;
              tmpParam.value = parameterList[parameter_i].parameter_value;
              tmpParam.entity = parameterList[parameter_i].entity_name;
              tmpParam.entity_id = parameterList[parameter_i].entity_id;
              tmpIntent.entities.push(tmpParam);

              //Check for common errors
              if (tmpParam.entity === null) {
                $scope.generateError = "Entity is null";
              }

              //Check for synonyms for this entity, and if it exists, lets also clone our current intent and replace the entity with the synonym
              var synonymList = synonyms.filter(synonym => synonym.entity_id === parameterList[parameter_i].entity_id);
              if (synonymList !== undefined) {
                for (synonym_i = 0; synonym_i <= synonymList.length - 1; synonym_i++) {
                  if (synonymList[synonym_i].synonym_reference === tmpParam.value) {
                    var tmpSynonymIntent = {};
                    var tmpSynonym = {};

                    tmpSynonymIntent.intent = tmpIntent.intent;
                    tmpSynonymIntent.text = tmpIntent.text.replace(tmpParam.value, synonymList[synonym_i].synonym_value);
                    tmpSynonymIntent.entities = [];
                    tmpSynonymIntent.expression_id = tmpIntent.expression_id;

                    var start = tmpSynonymIntent.text.indexOf(synonymList[synonym_i].synonym_value);
                    var end = synonymList[synonym_i].synonym_value.length + start;
                    tmpSynonym.start = start;
                    tmpSynonym.end = end;
                    tmpSynonym.value = tmpParam.value;
                    tmpSynonym.entity = tmpParam.entity;
                    tmpSynonym.entity_id = tmpParam.entity_id;

                    tmpSynonymIntent.entities.push(tmpSynonym);
                    tmpData.rasa_nlu_data.common_examples.push(tmpSynonymIntent);
                  }
                }
              }
            }
            tmpData.rasa_nlu_data.common_examples.push(tmpIntent);
          }
        }
      }
    }

    for (var i = 0; i <= tmpData.rasa_nlu_data.common_examples.length - 1; i++) {
      var parameterList = params.filter(param => param.expression_id === tmpData.rasa_nlu_data.common_examples[i].expression_id);
      var entities = [];
      if (tmpData.rasa_nlu_data.common_examples[i].entities.length !== parameterList.length) {
          var missingEntities = parameterList.filter(param => param.entity_id != tmpData.rasa_nlu_data.common_examples[i].entities[0].entity_id);
          for (parameter_i = 0; parameter_i <= missingEntities.length - 1; parameter_i++) {
            tmpParam = {};
            var start = tmpData.rasa_nlu_data.common_examples[i].text.indexOf(missingEntities[parameter_i].parameter_value);
            var end = missingEntities[parameter_i].parameter_value.length + start;
            tmpParam.start = start;
            tmpParam.end = end;
            tmpParam.value = missingEntities[parameter_i].parameter_value;
            tmpParam.entity = missingEntities[parameter_i].entity_name;
            //tmpParam.entity_id = missingEntities[parameter_i].entity_id;
            tmpData.rasa_nlu_data.common_examples[i].entities.push(tmpParam);
          }
      }
      delete tmpData.rasa_nlu_data.common_examples[i].expression_id;
    }

    exportData = tmpData;
    $scope.exportdata = tmpData;
    $scope.generateError = "";
  }

  function getRasaStatus() {
    Rasa_Status.get(function(statusdata) {
      Rasa_Config.get(function(configdata) {
        try {
          $rootScope.config = configdata.toJSON();
          $rootScope.config.isonline = 1;
          $rootScope.config.server_model_dirs_array = getAvailableModels(statusdata.available_models);
          if ($rootScope.config.server_model_dirs_array.length > 0) {
            $rootScope.modelname = $rootScope.config.server_model_dirs_array[0].name;
          } else {
            $rootScope.modelname = "Default";
          }

          if (statusdata !== undefined || statusdata.available_models !== undefined) {
            $rootScope.available_models = sortArrayByDate(getAvailableModels(statusdata.available_models), 'xdate');
            $rootScope.trainings_under_this_process = statusdata.trainings_under_this_process;
          }
        } catch (err) {
          console.log(err);
        }
      });
    });
  }
}
<commit_msg>- Corrects training endpoint<commit_after>angular
.module('app')
.controller('TrainingController', TrainingController)

function TrainingController($scope, $rootScope, $interval, $http, Rasa_Status, Agent, Intents, Expressions, ExpressionParameters, Rasa_Config) {
  var exportData;
  var statuscheck = $interval(getRasaStatus, 5000);
  $scope.generateError = "";
  $scope.trainings_under_this_process = 0;

  getRasaStatus();

  $scope.$on("$destroy", function(){
    $interval.cancel(statuscheck);
  });

  Agent.query(function(data) {
    $scope.agentList = data;
  });

  $scope.train = function() {
    var agentname = objectFindByKey($scope.agentList, 'agent_id', $scope.agent.agent_id).agent_name;

    var id = new XDate().toString('yyyyMMdd-HHmmss');
    $http.post(api_endpoint_v2 + "/rasa/train?name=" + agentname + "_" + id, JSON.stringify(exportData));
    //Minimize training data
    $scope.exportdata = {};
  }

  $scope.savetofile = function() {
      var data = new Blob([JSON.stringify($scope.exportdata, null, 2)], {type: 'text/plain'});

      var a = document.getElementById("a");
      a.download = "trainingdata.txt";
      a.href = URL.createObjectURL(data);
      a.click();
  }

  $scope.getData = function(agent_id) {
    //Get Intents, Expressions, Parameters/Entities, Synonyms
    var intent_i;
    var expression_i;
    var parameter_i;
    var intents;
    var expressions;
    var params;
    var synonyms;

    $http({method: 'GET', url: api_endpoint_v2 + "/agents/" + agent_id + "/intents"}).
    then(function(data) {
      intents = data.data;
      var intentIds = intents.map(function(item) { return item['intent_id']; }).toString();
      $http({method: 'GET', url: api_endpoint_v2 + "/intent_expressions?intent_ids=" + intentIds }).
      then(function(data) {
        expressions = data.data;
        var expressionIds = expressions.map(function(item) { return item['expression_id']; }).toString();
        $http({method: 'GET', url: api_endpoint_v2 + "/expression_parameters?expression_ids=" + expressionIds}).
        then(function(data) {
          params = data.data;
          var entityIds = params.map(function(item) { return item['entity_id']; }).toString();
          $http({method: 'GET', url: api_endpoint_v2 + '/entity_synonym_variants?entity_ids=' + entityIds}).
          then(function(data) {
            synonyms = data.data;
            generateData(intents, expressions, params, synonyms)
          }, function(error) {
            console.log(error);
          });
        }, function(error) {
          console.log(error);
        });
      }, function(error) {
        console.log(error);
      });
    }, function(error) {
      console.log(error);
    });
  }

  function generateData(intents, expressions, params, synonyms) {
    var tmpData = {};
    var tmpIntent = {};
    var tmpExpression = {};
    var tmpParam = {};
    tmpData.rasa_nlu_data = {}
    tmpData.rasa_nlu_data.common_examples = [];

    for (intent_i = 0; intent_i <= intents.length - 1; intent_i++) {
      var expressionList = expressions.filter(expression => expression.intent_id === intents[intent_i].intent_id);
      if (expressionList !== undefined) {
        for (expression_i = 0; expression_i <= expressionList.length - 1; expression_i++) {
          tmpIntent = {};
          tmpExpression = {};

          tmpIntent.intent = intents[intent_i].intent_name;
          tmpIntent.text = expressionList[expression_i].expression_text;
          tmpIntent.entities = [];
          tmpIntent.expression_id = expressionList[expression_i].expression_id;

          var parameterList = params.filter(param => param.expression_id === expressionList[expression_i].expression_id);
          var entities = [];
          if (parameterList !== undefined) {
            for (parameter_i = 0; parameter_i <= parameterList.length - 1; parameter_i++) {
              tmpParam = {};
              tmpParam.start = parameterList[parameter_i].parameter_start;
              tmpParam.end = parameterList[parameter_i].parameter_end;
              tmpParam.value = parameterList[parameter_i].parameter_value;
              tmpParam.entity = parameterList[parameter_i].entity_name;
              tmpParam.entity_id = parameterList[parameter_i].entity_id;
              tmpIntent.entities.push(tmpParam);

              //Check for common errors
              if (tmpParam.entity === null) {
                $scope.generateError = "Entity is null";
              }

              //Check for synonyms for this entity, and if it exists, lets also clone our current intent and replace the entity with the synonym
              var synonymList = synonyms.filter(synonym => synonym.entity_id === parameterList[parameter_i].entity_id);
              if (synonymList !== undefined) {
                for (synonym_i = 0; synonym_i <= synonymList.length - 1; synonym_i++) {
                  if (synonymList[synonym_i].synonym_reference === tmpParam.value) {
                    var tmpSynonymIntent = {};
                    var tmpSynonym = {};

                    tmpSynonymIntent.intent = tmpIntent.intent;
                    tmpSynonymIntent.text = tmpIntent.text.replace(tmpParam.value, synonymList[synonym_i].synonym_value);
                    tmpSynonymIntent.entities = [];
                    tmpSynonymIntent.expression_id = tmpIntent.expression_id;

                    var start = tmpSynonymIntent.text.indexOf(synonymList[synonym_i].synonym_value);
                    var end = synonymList[synonym_i].synonym_value.length + start;
                    tmpSynonym.start = start;
                    tmpSynonym.end = end;
                    tmpSynonym.value = tmpParam.value;
                    tmpSynonym.entity = tmpParam.entity;
                    tmpSynonym.entity_id = tmpParam.entity_id;

                    tmpSynonymIntent.entities.push(tmpSynonym);
                    tmpData.rasa_nlu_data.common_examples.push(tmpSynonymIntent);
                  }
                }
              }
            }
            tmpData.rasa_nlu_data.common_examples.push(tmpIntent);
          }
        }
      }
    }

    for (var i = 0; i <= tmpData.rasa_nlu_data.common_examples.length - 1; i++) {
      var parameterList = params.filter(param => param.expression_id === tmpData.rasa_nlu_data.common_examples[i].expression_id);
      var entities = [];
      if (tmpData.rasa_nlu_data.common_examples[i].entities.length !== parameterList.length) {
          var missingEntities = parameterList.filter(param => param.entity_id != tmpData.rasa_nlu_data.common_examples[i].entities[0].entity_id);
          for (parameter_i = 0; parameter_i <= missingEntities.length - 1; parameter_i++) {
            tmpParam = {};
            var start = tmpData.rasa_nlu_data.common_examples[i].text.indexOf(missingEntities[parameter_i].parameter_value);
            var end = missingEntities[parameter_i].parameter_value.length + start;
            tmpParam.start = start;
            tmpParam.end = end;
            tmpParam.value = missingEntities[parameter_i].parameter_value;
            tmpParam.entity = missingEntities[parameter_i].entity_name;
            //tmpParam.entity_id = missingEntities[parameter_i].entity_id;
            tmpData.rasa_nlu_data.common_examples[i].entities.push(tmpParam);
          }
      }
      delete tmpData.rasa_nlu_data.common_examples[i].expression_id;
    }

    exportData = tmpData;
    $scope.exportdata = tmpData;
    $scope.generateError = "";
  }

  function getRasaStatus() {
    Rasa_Status.get(function(statusdata) {
      Rasa_Config.get(function(configdata) {
        try {
          $rootScope.config = configdata.toJSON();
          $rootScope.config.isonline = 1;
          $rootScope.config.server_model_dirs_array = getAvailableModels(statusdata.available_models);
          if ($rootScope.config.server_model_dirs_array.length > 0) {
            $rootScope.modelname = $rootScope.config.server_model_dirs_array[0].name;
          } else {
            $rootScope.modelname = "Default";
          }

          if (statusdata !== undefined || statusdata.available_models !== undefined) {
            $rootScope.available_models = sortArrayByDate(getAvailableModels(statusdata.available_models), 'xdate');
            $rootScope.trainings_under_this_process = statusdata.trainings_under_this_process;
          }
        } catch (err) {
          console.log(err);
        }
      });
    });
  }
}
<|endoftext|>


<commit_before>import { calcDuration, convertSecToHHMMSS, debounce, isNonAnonLoggedInUser,
         readableDate } from './utility.js';
import { subscribeToPodcast, unsubscribeFromPodcast } from './podcastHelper.js';
import { sendGoogleAnalyticsPlayerPageView,
         sendGoogleAnalyticsEvent } from './googleAnalytics.js';
import { isMobileOrTablet } from './browserSupportDetection.js';

// Set default values for vars that handle player crashes and autoplay functionality
window.restartAttempts = 0;
window.lastPlaybackPosition = -1;
window.endTimeHasBeenReached = false;

// Load the player
if (isEmptyPlaylist !== true) {
  setPlayerInfo();
  // TODO: remove autoplay on mobile devices since they do not support autoplay
  // TODO: or find some kind of way to let autoplay be enabled in mobile browsers
  createAutoplayBtn();
  createAndAppendAudio();
  onScrollCondensePlayerView();
} else {
  var isEmptyPlaylistEl = '
This playlist has no episodes or clips added to it.

 Click the  icon while an episode or clip is playing to add it to a playlist.
';
  $(isEmptyPlaylistEl).insertAfter('#player');
}

// Podcast / Episode / Clip variables added to the window
// object in player.html

function loadMediaRef (index, shouldPlay) {
  var item = mediaRefs[index];

  // Only clips have a startTime and endTime
  startTime = item.startTime;
  endTime = item.endTime;

  if (window.startTime === 0 && window.endTime === null) {
    isEpisode = true;
  } else {
    isEpisode = false;
  }

  podcastTitle = item.podcastTitle;
  podcastImageURL = item.podcastImageURL;
  episodeTitle = item.episodeTitle;
  episodeMediaURL = item.episodeMediaURL;
  episodePubDate = item.episodePubDate;
  description = item.title;
  isSubscribed = item.isSubscribed;

  if (isEpisode === false) {
    mediaRefId = item.id;
  } else {
    mediaRefId = 'episode_' + item.episodeMediaURL;
  }

  window.location.hash = index + 1;

  setPlayerInfo();
  createAndAppendAudio();
  if (shouldPlay) {
    audio.play();
  }

  sendGoogleAnalyticsPlayerPageView();

}

export function previewStartTime (startTime, endTime) {
  window.endTimeHasBeenReached = false;
  window.endTime = endTime;
  audio.currentTime = window.startTime = startTime;
  audio.play();

  sendGoogleAnalyticsEvent('Media Player', 'Preview Start Time');
}

export function previewEndTime (endTime) {
  window.endTimeHasBeenReached = false;
  window.endTime = endTime;
  audio.currentTime = endTime - 3;
  audio.play();

  sendGoogleAnalyticsEvent('Media Player', 'Preview End Time');
}

function setPlayerInfo () {

  if (window.startTime === 0 && window.endTime === null) {
    isEpisode = true;
  } else {
    isEpisode = false;
    endTime = parseInt(window.endTime)
  }

  $('#player').attr('data-id', window.mediaRefId);

  $('#player-header').show();

  if (isEpisode === false) {
    var duration = calcDuration(startTime, endTime);
    $('#player-stats-duration').html('Clip: ' + convertSecToHHMMSS(startTime) + ' to ' + convertSecToHHMMSS(endTime));
    $('#player-condensed-text').html('Clip: ' + convertSecToHHMMSS(startTime) + ' to ' + convertSecToHHMMSS(endTime) + ' – ' + description);
    $('#player-condensed-text').addClass('should-show');
  } else {
    $('#player-stats-duration').html('Full Episode');
  }

  if (isPlaylist && !isEpisode) {
    $('#player-stats-duration-link').html('')
  } else if (isPlaylist && isEpisode) {
    // TODO: this is broken
    $('#player-stats-duration-link').html('')
  }

  $('#player-condensed-title a').html(podcastTitle);
  // TODO: this is broken
  $('#player-condensed-title a').attr('href', '/podcasts?feedURL=' + podcastFeedURL);
  $('#player-condensed-sub-title').html(episodeTitle);
  $('#player-condensed-image img').attr('src', podcastImageURL);

  $('#player-podcast-title a').attr('href', '/podcasts/alias?feedURL=' + podcastFeedURL);
  $('#player-podcast-title a').html(podcastTitle);

  // TODO: this is broken
  $('#player-sub-title a').attr('href', '/episodes/alias?mediaURL=' + episodeMediaURL);
  $('#player-sub-title a').html(episodeTitle);

  $('#player-image a').attr('href', '/podcasts?feedURL=' + podcastFeedURL);
  $('#player-image img').attr('src', podcastImageURL);
  $('#player-stats-pub-date').html(readableDate(episodePubDate));

  $('#player-time-jump-back').html(' 15s');
  $('#player-time-jump-forward').html('15s ');
  $('#toggle-make-clip-btn').html('');
  $('#toggle-playlist-btn').html('');
  $('#toggle-recommend-btn').html('');

  if ($('#player-hr').length < 1) {
    $('
').insertAfter('#player-functions');
  }

  if (description) {
    let truncDescription = description.substring(0, 286);

    // Add "show more" if description was truncated
    if (truncDescription.length > 285) {
      // If last character is a space, remove it
      if(/\s+$/.test(truncDescription)) {
        truncDescription = truncDescription.slice(0,-1)
      }

      truncDescription += "... show more";
    }

    description += '
';
    truncDescription += '
';

    $('#player-description-truncated').html(truncDescription);
    $('#player-description-full').html(description);

    $('#player-description-truncated').show();
    $('#player-description-full').hide();

    $('#player-description-truncated').on('click', () => {
      $('#player-description-truncated').hide();
      $('#player-description-full').show();
    })
  }

  if (isSubscribed && isSubscribed != 'false') {
    $('#player-podcast-subscribe').html('');
    $('#player-podcast-subscribe').attr('title', 'Unsubscribe from podcast');
  } else {
    $('#player-podcast-subscribe').html('');
    $('#player-podcast-subscribe').attr('title', 'Subscribe to podcast');
  }

  $('#player-podcast-subscribe').on('click', function () {
    if (!isNonAnonLoggedInUser()) {
      alert('Please login to subscribe to this podcast.');
      return;
    }

    if ($(this).children().hasClass('fa-star-o')) {
      $('#player-podcast-subscribe').html('');
      $('#player-podcast-subscribe').attr('title', 'Unsubscribe from podcast');
      subscribeToPodcast(podcastFeedURL);
    } else {
      $('#player-podcast-subscribe').html('');
      $('#player-podcast-subscribe').attr('title', 'Subscribe to podcast');
      unsubscribeFromPodcast(podcastFeedURL);
    }
  });

  window.restartAttempts = 0;
  window.lastPlaybackPosition = -1;
  window.endTimeHasBeenReached = false;

  var playerWidth = $('#player-inner').width();
  $('#player-condensed-inner').css('width', playerWidth);

  let updateCondensedPlayerWidth = debounce(function () {
    var playerWidth = $('#player-inner').width();
    $('#player-condensed-inner').css('width', playerWidth);
  }, 150);

  window.addEventListener('resize', updateCondensedPlayerWidth);

}

function createAndAppendAudio () {

  // If a new media file is loaded, reappend audio element
  if (episodeMediaURL !== previousEpisodeMediaURL) {
    window.previousEpisodeMediaURL = episodeMediaURL;
    // If audio player elements are already on the page, remove them first.
    $('.mejs-offscreen').remove();
    $('.mejs-container').remove();

    window.audio = document.createElement('audio');
    audio.setAttribute('src', episodeMediaURL);
    audio.setAttribute('type', 'audio/mpeg');
    audio.setAttribute('codecs', 'mp3');
    audio.preload = "auto";
    $('#player').append(audio);

    $('audio').mediaelementplayer({
      // the order of controls you want on the control bar (and other plugins below)
      features: ['playpause', 'current', 'progress', 'duration', 'volume', 'fasterslower'],
      alwaysShowHours: true,
      alwaysShowControls: true
    });

  }

  audio.onloadedmetadata = function() {
    // NOTE: If the lastPlaybackPosition is greater than -1, then the audio player must
    // have crashed and then restarted, and we should resume from the last saved
    // playback position. Else begin from the clip start time.
    if (lastPlaybackPosition > -1) {
      audio.currentTime = window.lastPlaybackPosition;
    } else {
      audio.currentTime = window.startTime || 0;
    }
  };

  // The oncanplaythrough event gets called whenever the currentTime changes.
  // We only want oncanplaythrough to trigger autoplay ONCE when the file first
  // loads, and not when the 15 sec time jump buttons are pressed.
  var autoplayOnceAtBeginning = false;
  audio.oncanplaythrough = function() {
    var autoplay = $.cookie('autoplay');
    if (autoplay === 'true' && autoplayOnceAtBeginning === false) {
      autoplayOnceAtBeginning = true;
      audio.play();
    }
  }

  // When playing a clip, prevent issue where the media file starts playing
  // from the beginning for a split second before adjusting the startTime.
  var pauseBeforeFirstPlay = false;
  audio.onplaying = function() {
    if (!pauseBeforeFirstPlay) {
      audio.pause();
      setTimeout(function() {
        audio.play();
        pauseBeforeFirstPlay = true;
      }, 1);
    }
  }

  audio.ontimeupdate = function() {

    // Skip to start time once when the user first hits play on mobile devices
    if (lastPlaybackPosition === -1) {
      audio.currentTime = startTime;
    }

    // Stop the clip once when the end time has been reached
    if (Math.floor(audio.currentTime) === endTime && endTimeHasBeenReached === false) {
      endTimeHasBeenReached = true;
      audio.pause();

      var autoplay = $.cookie('autoplay');
      if (isPlaylist && autoplay === 'true') {
        if (urlHashIndexValue < mediaRefs.length - 1) {
          urlHashIndexValue++;
          window.location.hash = urlHashIndexValue;
          lastPlaybackPosition = -1;
          loadMediaRef(urlHashIndexValue, true)
          return;
        }
      }
    }

    // TODO: Can this be made more efficient than rewriting the lastPlaybackPosition
    // whenever time updates?
    lastPlaybackPosition = audio.currentTime;

  };

  audio.onerror = function(e) {
    switch (e.target.error.code) {
      case e.target.error.MEDIA_ERR_ABORTED:
        console.log('Aborted the video playback.');
        break;
      // Chrome will frequently throw a MEDIA_ERR_NETWORK error and crash when seeking
      // to a position in a clip. I have encountered the issue with native HTML 5 Chrome
      // components, as well as with 3rd party libraries like JWPlayer and MediaElement.
      // The only work around for this bug I have found is to listen for the error,
      // then remove the <audio> element and recreate and append the audio element.
      // TODO: Is there a better work around or resolution for the Chrome bug?
      case e.target.error.MEDIA_ERR_NETWORK:
        console.log('A network error caused the audio download to fail.');
        if (restartAttempts < 5) {
          restartAttempts++;
          $('#player').empty();
          createAndAppendAudio();
        }
        break;
      case e.target.error.MEDIA_ERR_DECODE:
        console.log('The audio playback was aborted due to a corruption problem or because the video used features your browser did not support.');
        break;
      case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
        console.log('The video audio not be loaded, either because the server or network failed or because the format is not supported.');
        break;
      default:
        console.log('An unknown error occurred.');
        break;
    }
  };

};

$('#player-time-jump-forward').on('click', function() {
  audio.currentTime = audio.currentTime + 15;
});

$('#player-time-jump-back').on('click', function() {
  audio.currentTime = audio.currentTime - 15;
});

$('#player-autoplay').on('click', function() {
  toggleAutoplay();
});

function toggleAutoplay () {
  var autoplay = $.cookie('autoplay');
  if (autoplay !== 'true') {
    $.cookie('autoplay', 'true', { path: '/' });
    $('#player-autoplay').html('Autoplay On');
    sendGoogleAnalyticsEvent('Media Player', 'Toggle Autoplay On');
  } else {
    $.cookie('autoplay', 'false', { path: '/' });
    $('#player-autoplay').html('Autoplay Off');
    sendGoogleAnalyticsEvent('Media Player', 'Toggle Autoplay Off');
  }
}

function createAutoplayBtn () {
  if (!isMobileOrTablet()) {
    var autoplay = $.cookie('autoplay');
    if (autoplay === 'true') {
      $('#player-autoplay').html('Autoplay On');
    } else {
      $.cookie('autoplay', 'false', { path: '/' });
      $('#player-autoplay').html('Autoplay Off');
    }
  }
}

function restart () {
  audio.pause();
  endTimeHasBeenReached = false;
  audio.currentTime = startTime;
  audio.play();
  sendGoogleAnalyticsEvent('Media Player', 'Restart');
}

$('#player-stats-duration').on('click', function () {
  restart();
});

$('.playlist-item').on('click', function() {
  if (isPlayerPage) {
    var index = $(".playlist-item").index(this);
    urlHashIndexValue = index;
    loadMediaRef(index, true);
    sendGoogleAnalyticsEvent('Media Player', 'Playlist Item Clicked');
  }
});

function onScrollCondensePlayerView () {

  var topOfPlayer = $("#player").offset().top;
  var heightOfPlayer = $("#player").outerHeight();
  var bottomOfPlayer = topOfPlayer + heightOfPlayer;

  var topOfPlayerContainer = $('#player-container').offset().top;
  // -145 to prevent screen from jumping when switching to a condensed view
  // HACK: we shouldn't need something like this, remove after refactoring player /  condensed player
  var heightOfPlayerContainer = $('#player-container').outerHeight() - 145;
  var bottomOfPlayerContainer = topOfPlayerContainer + heightOfPlayerContainer;

  let condenseOnScroll = debounce(function () {
    if($(window).scrollTop() > (bottomOfPlayer)){
     $('html').attr('style', 'padding-top: ' + bottomOfPlayerContainer + 'px;' );

     $('#player-container').addClass('condensed');

    } else {
     $('html').attr('style', '');
     $('#player-container').removeClass('condensed');
    }
  }, 20)

  window.addEventListener('scroll', condenseOnScroll);

}

function destroyPlayerAndAudio () {
  var audioElArray = $('#player audio');
  if (audioElArray.length > 0) {
    var audioEl = audioElArray[0];
    audioEl.pause();
    audioEl.src = '';
    audioEl.load();
  }
  audio = null;
  $('#player').html('');
}
<commit_msg>Fix playlist item mediaRefId bug<commit_after>import { calcDuration, convertSecToHHMMSS, debounce, isNonAnonLoggedInUser,
         readableDate } from './utility.js';
import { subscribeToPodcast, unsubscribeFromPodcast } from './podcastHelper.js';
import { sendGoogleAnalyticsPlayerPageView,
         sendGoogleAnalyticsEvent } from './googleAnalytics.js';
import { isMobileOrTablet } from './browserSupportDetection.js';

// Set default values for vars that handle player crashes and autoplay functionality
window.restartAttempts = 0;
window.lastPlaybackPosition = -1;
window.endTimeHasBeenReached = false;

// Load the player
if (isEmptyPlaylist !== true) {
  setPlayerInfo();
  // TODO: remove autoplay on mobile devices since they do not support autoplay
  // TODO: or find some kind of way to let autoplay be enabled in mobile browsers
  createAutoplayBtn();
  createAndAppendAudio();
  onScrollCondensePlayerView();
} else {
  var isEmptyPlaylistEl = '
This playlist has no episodes or clips added to it.

 Click the  icon while an episode or clip is playing to add it to a playlist.
';
  $(isEmptyPlaylistEl).insertAfter('#player');
}

// Podcast / Episode / Clip variables added to the window
// object in player.html

function loadMediaRef (index, shouldPlay) {
  var item = mediaRefs[index];

  // Only clips have a startTime and endTime
  startTime = item.startTime;
  endTime = item.endTime;

  if (window.startTime === 0 && window.endTime === null) {
    isEpisode = true;
  } else {
    isEpisode = false;
  }

  podcastTitle = item.podcastTitle;
  podcastImageURL = item.podcastImageURL;
  episodeTitle = item.episodeTitle;
  episodeMediaURL = item.episodeMediaURL;
  episodePubDate = item.episodePubDate;
  description = item.title;
  isSubscribed = item.isSubscribed;
  mediaRefId = item.id;

  window.location.hash = index + 1;

  setPlayerInfo();
  createAndAppendAudio();
  if (shouldPlay) {
    audio.play();
  }

  sendGoogleAnalyticsPlayerPageView();

}

export function previewStartTime (startTime, endTime) {
  window.endTimeHasBeenReached = false;
  window.endTime = endTime;
  audio.currentTime = window.startTime = startTime;
  audio.play();

  sendGoogleAnalyticsEvent('Media Player', 'Preview Start Time');
}

export function previewEndTime (endTime) {
  window.endTimeHasBeenReached = false;
  window.endTime = endTime;
  audio.currentTime = endTime - 3;
  audio.play();

  sendGoogleAnalyticsEvent('Media Player', 'Preview End Time');
}

function setPlayerInfo () {

  if (window.startTime === 0 && window.endTime === null) {
    isEpisode = true;
  } else {
    isEpisode = false;
    endTime = parseInt(window.endTime)
  }

  $('#player').attr('data-id', window.mediaRefId);

  $('#player-header').show();

  if (isEpisode === false) {
    var duration = calcDuration(startTime, endTime);
    $('#player-stats-duration').html('Clip: ' + convertSecToHHMMSS(startTime) + ' to ' + convertSecToHHMMSS(endTime));
    $('#player-condensed-text').html('Clip: ' + convertSecToHHMMSS(startTime) + ' to ' + convertSecToHHMMSS(endTime) + ' – ' + description);
    $('#player-condensed-text').addClass('should-show');
  } else {
    $('#player-stats-duration').html('Full Episode');
  }

  if (isPlaylist && !isEpisode) {
    $('#player-stats-duration-link').html('')
  } else if (isPlaylist && isEpisode) {
    // TODO: this is broken
    $('#player-stats-duration-link').html('')
  }

  $('#player-condensed-title a').html(podcastTitle);
  // TODO: this is broken
  $('#player-condensed-title a').attr('href', '/podcasts?feedURL=' + podcastFeedURL);
  $('#player-condensed-sub-title').html(episodeTitle);
  $('#player-condensed-image img').attr('src', podcastImageURL);

  $('#player-podcast-title a').attr('href', '/podcasts/alias?feedURL=' + podcastFeedURL);
  $('#player-podcast-title a').html(podcastTitle);

  // TODO: this is broken
  $('#player-sub-title a').attr('href', '/episodes/alias?mediaURL=' + episodeMediaURL);
  $('#player-sub-title a').html(episodeTitle);

  $('#player-image a').attr('href', '/podcasts?feedURL=' + podcastFeedURL);
  $('#player-image img').attr('src', podcastImageURL);
  $('#player-stats-pub-date').html(readableDate(episodePubDate));

  $('#player-time-jump-back').html(' 15s');
  $('#player-time-jump-forward').html('15s ');
  $('#toggle-make-clip-btn').html('');
  $('#toggle-playlist-btn').html('');
  $('#toggle-recommend-btn').html('');

  if ($('#player-hr').length < 1) {
    $('
').insertAfter('#player-functions');
  }

  if (description) {
    let truncDescription = description.substring(0, 286);

    // Add "show more" if description was truncated
    if (truncDescription.length > 285) {
      // If last character is a space, remove it
      if(/\s+$/.test(truncDescription)) {
        truncDescription = truncDescription.slice(0,-1)
      }

      truncDescription += "... show more";
    }

    description += '
';
    truncDescription += '
';

    $('#player-description-truncated').html(truncDescription);
    $('#player-description-full').html(description);

    $('#player-description-truncated').show();
    $('#player-description-full').hide();

    $('#player-description-truncated').on('click', () => {
      $('#player-description-truncated').hide();
      $('#player-description-full').show();
    })
  }

  if (isSubscribed && isSubscribed != 'false') {
    $('#player-podcast-subscribe').html('');
    $('#player-podcast-subscribe').attr('title', 'Unsubscribe from podcast');
  } else {
    $('#player-podcast-subscribe').html('');
    $('#player-podcast-subscribe').attr('title', 'Subscribe to podcast');
  }

  $('#player-podcast-subscribe').on('click', function () {
    if (!isNonAnonLoggedInUser()) {
      alert('Please login to subscribe to this podcast.');
      return;
    }

    if ($(this).children().hasClass('fa-star-o')) {
      $('#player-podcast-subscribe').html('');
      $('#player-podcast-subscribe').attr('title', 'Unsubscribe from podcast');
      subscribeToPodcast(podcastFeedURL);
    } else {
      $('#player-podcast-subscribe').html('');
      $('#player-podcast-subscribe').attr('title', 'Subscribe to podcast');
      unsubscribeFromPodcast(podcastFeedURL);
    }
  });

  window.restartAttempts = 0;
  window.lastPlaybackPosition = -1;
  window.endTimeHasBeenReached = false;

  var playerWidth = $('#player-inner').width();
  $('#player-condensed-inner').css('width', playerWidth);

  let updateCondensedPlayerWidth = debounce(function () {
    var playerWidth = $('#player-inner').width();
    $('#player-condensed-inner').css('width', playerWidth);
  }, 150);

  window.addEventListener('resize', updateCondensedPlayerWidth);

}

function createAndAppendAudio () {

  // If a new media file is loaded, reappend audio element
  if (episodeMediaURL !== previousEpisodeMediaURL) {
    window.previousEpisodeMediaURL = episodeMediaURL;
    // If audio player elements are already on the page, remove them first.
    $('.mejs-offscreen').remove();
    $('.mejs-container').remove();

    window.audio = document.createElement('audio');
    audio.setAttribute('src', episodeMediaURL);
    audio.setAttribute('type', 'audio/mpeg');
    audio.setAttribute('codecs', 'mp3');
    audio.preload = "auto";
    $('#player').append(audio);

    $('audio').mediaelementplayer({
      // the order of controls you want on the control bar (and other plugins below)
      features: ['playpause', 'current', 'progress', 'duration', 'volume', 'fasterslower'],
      alwaysShowHours: true,
      alwaysShowControls: true
    });

  }

  audio.onloadedmetadata = function() {
    // NOTE: If the lastPlaybackPosition is greater than -1, then the audio player must
    // have crashed and then restarted, and we should resume from the last saved
    // playback position. Else begin from the clip start time.
    if (lastPlaybackPosition > -1) {
      audio.currentTime = window.lastPlaybackPosition;
    } else {
      audio.currentTime = window.startTime || 0;
    }
  };

  // The oncanplaythrough event gets called whenever the currentTime changes.
  // We only want oncanplaythrough to trigger autoplay ONCE when the file first
  // loads, and not when the 15 sec time jump buttons are pressed.
  var autoplayOnceAtBeginning = false;
  audio.oncanplaythrough = function() {
    var autoplay = $.cookie('autoplay');
    if (autoplay === 'true' && autoplayOnceAtBeginning === false) {
      autoplayOnceAtBeginning = true;
      audio.play();
    }
  }

  // When playing a clip, prevent issue where the media file starts playing
  // from the beginning for a split second before adjusting the startTime.
  var pauseBeforeFirstPlay = false;
  audio.onplaying = function() {
    if (!pauseBeforeFirstPlay) {
      audio.pause();
      setTimeout(function() {
        audio.play();
        pauseBeforeFirstPlay = true;
      }, 1);
    }
  }

  audio.ontimeupdate = function() {

    // Skip to start time once when the user first hits play on mobile devices
    if (lastPlaybackPosition === -1) {
      audio.currentTime = startTime;
    }

    // Stop the clip once when the end time has been reached
    if (Math.floor(audio.currentTime) === endTime && endTimeHasBeenReached === false) {
      endTimeHasBeenReached = true;
      audio.pause();

      var autoplay = $.cookie('autoplay');
      if (isPlaylist && autoplay === 'true') {
        if (urlHashIndexValue < mediaRefs.length - 1) {
          urlHashIndexValue++;
          window.location.hash = urlHashIndexValue;
          lastPlaybackPosition = -1;
          loadMediaRef(urlHashIndexValue, true)
          return;
        }
      }
    }

    // TODO: Can this be made more efficient than rewriting the lastPlaybackPosition
    // whenever time updates?
    lastPlaybackPosition = audio.currentTime;

  };

  audio.onerror = function(e) {
    switch (e.target.error.code) {
      case e.target.error.MEDIA_ERR_ABORTED:
        console.log('Aborted the video playback.');
        break;
      // Chrome will frequently throw a MEDIA_ERR_NETWORK error and crash when seeking
      // to a position in a clip. I have encountered the issue with native HTML 5 Chrome
      // components, as well as with 3rd party libraries like JWPlayer and MediaElement.
      // The only work around for this bug I have found is to listen for the error,
      // then remove the <audio> element and recreate and append the audio element.
      // TODO: Is there a better work around or resolution for the Chrome bug?
      case e.target.error.MEDIA_ERR_NETWORK:
        console.log('A network error caused the audio download to fail.');
        if (restartAttempts < 5) {
          restartAttempts++;
          $('#player').empty();
          createAndAppendAudio();
        }
        break;
      case e.target.error.MEDIA_ERR_DECODE:
        console.log('The audio playback was aborted due to a corruption problem or because the video used features your browser did not support.');
        break;
      case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
        console.log('The video audio not be loaded, either because the server or network failed or because the format is not supported.');
        break;
      default:
        console.log('An unknown error occurred.');
        break;
    }
  };

};

$('#player-time-jump-forward').on('click', function() {
  audio.currentTime = audio.currentTime + 15;
});

$('#player-time-jump-back').on('click', function() {
  audio.currentTime = audio.currentTime - 15;
});

$('#player-autoplay').on('click', function() {
  toggleAutoplay();
});

function toggleAutoplay () {
  var autoplay = $.cookie('autoplay');
  if (autoplay !== 'true') {
    $.cookie('autoplay', 'true', { path: '/' });
    $('#player-autoplay').html('Autoplay On');
    sendGoogleAnalyticsEvent('Media Player', 'Toggle Autoplay On');
  } else {
    $.cookie('autoplay', 'false', { path: '/' });
    $('#player-autoplay').html('Autoplay Off');
    sendGoogleAnalyticsEvent('Media Player', 'Toggle Autoplay Off');
  }
}

function createAutoplayBtn () {
  if (!isMobileOrTablet()) {
    var autoplay = $.cookie('autoplay');
    if (autoplay === 'true') {
      $('#player-autoplay').html('Autoplay On');
    } else {
      $.cookie('autoplay', 'false', { path: '/' });
      $('#player-autoplay').html('Autoplay Off');
    }
  }
}

function restart () {
  audio.pause();
  endTimeHasBeenReached = false;
  audio.currentTime = startTime;
  audio.play();
  sendGoogleAnalyticsEvent('Media Player', 'Restart');
}

$('#player-stats-duration').on('click', function () {
  restart();
});

$('.playlist-item').on('click', function() {
  if (isPlayerPage) {
    var index = $(".playlist-item").index(this);
    urlHashIndexValue = index;
    loadMediaRef(index, true);
    sendGoogleAnalyticsEvent('Media Player', 'Playlist Item Clicked');
  }
});

function onScrollCondensePlayerView () {

  var topOfPlayer = $("#player").offset().top;
  var heightOfPlayer = $("#player").outerHeight();
  var bottomOfPlayer = topOfPlayer + heightOfPlayer;

  var topOfPlayerContainer = $('#player-container').offset().top;
  // -145 to prevent screen from jumping when switching to a condensed view
  // HACK: we shouldn't need something like this, remove after refactoring player /  condensed player
  var heightOfPlayerContainer = $('#player-container').outerHeight() - 145;
  var bottomOfPlayerContainer = topOfPlayerContainer + heightOfPlayerContainer;

  let condenseOnScroll = debounce(function () {
    if($(window).scrollTop() > (bottomOfPlayer)){
     $('html').attr('style', 'padding-top: ' + bottomOfPlayerContainer + 'px;' );

     $('#player-container').addClass('condensed');

    } else {
     $('html').attr('style', '');
     $('#player-container').removeClass('condensed');
    }
  }, 20)

  window.addEventListener('scroll', condenseOnScroll);

}

function destroyPlayerAndAudio () {
  var audioElArray = $('#player audio');
  if (audioElArray.length > 0) {
    var audioEl = audioElArray[0];
    audioEl.pause();
    audioEl.src = '';
    audioEl.load();
  }
  audio = null;
  $('#player').html('');
}
<|endoftext|>


<commit_before>define([
    'flight/lib/component',
    'flight/lib/registry',
    'tpl!./detail',
    'util/vertex/formatters'
], function(defineComponent, registry, template, F) {
    'use strict';

    return defineComponent(Detail);

    function Detail() {

        this.defaultAttrs({
            mapCoordinatesSelector: '.map-coordinates',
            detailTypeContentSelector: '.type-content'
        });

        this.after('initialize', function() {
            this.on('click', {
                mapCoordinatesSelector: this.onMapCoordinatesClicked
            });
            this.on('finishedLoadingTypeContent', this.onFinishedTypeContent);

            this.on(document, 'objectsSelected', this.onObjectsSelected);
            this.on('selectObjects', this.onSelectObjects);
            this.preventDropEventsFromPropagating();

            this.before('teardown', this.teardownComponents);

            this.$node.html(template({}));

            if (this.attr.loadGraphVertexData) {
                this.onObjectsSelected(null, { vertices: [this.attr.loadGraphVertexData] });
            }
        });

        this.onSelectObjects = function(event, data) {
            if (!data.focus) {
                this.onObjectsSelected(null, data);
            }
        };

        this.onFinishedTypeContent = function() {
            this.$node.removeClass('loading');
        };

        // Ignore drop events so they don't propagate to the graph/map
        this.preventDropEventsFromPropagating = function() {
            this.$node.droppable({ tolerance: 'pointer', accept: '*' });
        };

        this.onMapCoordinatesClicked = function(evt, data) {
            evt.preventDefault();
            var $target = $(evt.target).closest('a');
            this.trigger('mapCenter', $target.data());
        };

        this.onObjectsSelected = function(evt, data) {
            var self = this,
                vertices = data.vertices,
                edges = data.edges,
                moduleName, moduleData;

            if (!vertices.length && !edges.length) {
                var pane = this.$node.closest('.detail-pane');

                this.cancelTransitionTeardown = false;

                return pane.on(TRANSITION_END, function(e) {
                    if (/transform/.test(e.originalEvent && e.originalEvent.propertyName)) {
                        if (self.cancelTransitionTeardown !== true) {
                            self.teardownComponents();
                        }
                        pane.off(TRANSITION_END);
                    }
                });
            }

            this.cancelTransitionTeardown = true;
            this.teardownComponents();
            this.$node.addClass('loading');

            if (vertices.length > 1) {
                moduleName = 'multiple';
                moduleData = vertices;
            } else if (vertices.length === 1) {
                var vertex = vertices[0],
                    type = vertex.concept && vertex.concept.displayType ||
                        (F.vertex.isEdge(vertex) ? 'relationship' : 'entity');

                if (type === 'relationship') {
                    moduleName = type;
                } else {
                    moduleName = (((type != 'document' &&
                                    type != 'image' &&
                                    type != 'video' &&
                                    type != 'audio') ? 'entity' : 'artifact'
                    ) || 'entity').toLowerCase();
                }
                moduleData = vertex;
            } else {
                moduleName = 'relationship';
                moduleData = edges[0];
            }

            moduleName = moduleName.toLowerCase();

            require([
                'detail/' + moduleName + '/' + moduleName,
            ], function(Module) {
                Module.attachTo(self.select('detailTypeContentSelector'), {
                    data: moduleData,
                    highlightStyle: self.attr.highlightStyle,
                    focus: data.focus
                });
            });
        };

        this.teardownComponents = function() {
            this.select('detailTypeContentSelector').teardownAllComponents();
        }
    }
});
<commit_msg>Unique the selected objects by id before choosing detail pane type<commit_after>define([
    'flight/lib/component',
    'flight/lib/registry',
    'tpl!./detail',
    'util/vertex/formatters'
], function(defineComponent, registry, template, F) {
    'use strict';

    return defineComponent(Detail);

    function Detail() {

        this.defaultAttrs({
            mapCoordinatesSelector: '.map-coordinates',
            detailTypeContentSelector: '.type-content'
        });

        this.after('initialize', function() {
            this.on('click', {
                mapCoordinatesSelector: this.onMapCoordinatesClicked
            });
            this.on('finishedLoadingTypeContent', this.onFinishedTypeContent);

            this.on(document, 'objectsSelected', this.onObjectsSelected);
            this.on('selectObjects', this.onSelectObjects);
            this.preventDropEventsFromPropagating();

            this.before('teardown', this.teardownComponents);

            this.$node.html(template({}));

            if (this.attr.loadGraphVertexData) {
                this.onObjectsSelected(null, { vertices: [this.attr.loadGraphVertexData] });
            }
        });

        this.onSelectObjects = function(event, data) {
            if (!data.focus) {
                this.onObjectsSelected(null, data);
            }
        };

        this.onFinishedTypeContent = function() {
            this.$node.removeClass('loading');
        };

        // Ignore drop events so they don't propagate to the graph/map
        this.preventDropEventsFromPropagating = function() {
            this.$node.droppable({ tolerance: 'pointer', accept: '*' });
        };

        this.onMapCoordinatesClicked = function(evt, data) {
            evt.preventDefault();
            var $target = $(evt.target).closest('a');
            this.trigger('mapCenter', $target.data());
        };

        this.onObjectsSelected = function(evt, data) {
            var self = this,
                vertices = data.vertices,
                edges = data.edges,
                moduleName, moduleData;

            if (!vertices.length && !edges.length) {
                var pane = this.$node.closest('.detail-pane');

                this.cancelTransitionTeardown = false;

                return pane.on(TRANSITION_END, function(e) {
                    if (/transform/.test(e.originalEvent && e.originalEvent.propertyName)) {
                        if (self.cancelTransitionTeardown !== true) {
                            self.teardownComponents();
                        }
                        pane.off(TRANSITION_END);
                    }
                });
            }

            this.cancelTransitionTeardown = true;
            this.teardownComponents();
            this.$node.addClass('loading');

            vertices = _.unique(vertices, 'id');

            if (vertices.length > 1) {
                moduleName = 'multiple';
                moduleData = vertices;
            } else if (vertices.length === 1) {
                var vertex = vertices[0],
                    type = vertex.concept && vertex.concept.displayType ||
                        (F.vertex.isEdge(vertex) ? 'relationship' : 'entity');

                if (type === 'relationship') {
                    moduleName = type;
                } else {
                    moduleName = (((type != 'document' &&
                                    type != 'image' &&
                                    type != 'video' &&
                                    type != 'audio') ? 'entity' : 'artifact'
                    ) || 'entity').toLowerCase();
                }
                moduleData = vertex;
            } else {
                moduleName = 'relationship';
                moduleData = edges[0];
            }

            moduleName = moduleName.toLowerCase();

            require([
                'detail/' + moduleName + '/' + moduleName,
            ], function(Module) {
                Module.attachTo(self.select('detailTypeContentSelector'), {
                    data: moduleData,
                    highlightStyle: self.attr.highlightStyle,
                    focus: data.focus
                });
            });
        };

        this.teardownComponents = function() {
            this.select('detailTypeContentSelector').teardownAllComponents();
        }
    }
});
<|endoftext|>


<commit_before>'use strict';

var settings = {
  "userPoolId": "eu-west-1_2mZqlM8LH",
  "applicationId": "4r317aae4nln2kao09knpurlc2",
  "identityPoolId": "eu-west-1:b0f2d0d1-615c-44c8-9708-2e71275e96b6",
  "bucketName": "test.cognito-auth.example.io"
};

angular.module('demoApp', [
  'ngFileUpload',
  'mpt.cognito-auth'
])

.constant('CognitoAuthConfig', {
  AWS_REGION: 'eu-west-1',
  AWS_USER_POOL_ID: settings.userPoolId,
  AWS_APP_ID: settings.applicationId,
  AWS_ID_POOL_ID: settings.identityPoolId,
  TRACE: true,
})

.constant('CognitoAuthS3Config', {
  BUCKET_REGION: 'eu-west-1',
  BUCKET_NAME: settings.bucketName,
  TRACE: true,
})

;
<commit_msg>demo: update with new pool IDs<commit_after>'use strict';

var settings = {
  "userPoolId": "eu-west-1_X44yuIZJd",
  "applicationId": "39hrf722hk1n7pa0ldgcbvfuo0",
  "identityPoolId": "eu-west-1:a3c637d7-ccd9-4405-96f0-522ba7ee5394",
  "bucketName": "s3-test.databatix.com",
};

angular.module('demoApp', [
  'ngFileUpload',
  'mpt.cognito-auth'
])

.constant('CognitoAuthConfig', {
  AWS_REGION: 'eu-west-1',
  AWS_USER_POOL_ID: settings.userPoolId,
  AWS_APP_ID: settings.applicationId,
  AWS_ID_POOL_ID: settings.identityPoolId,
  TRACE: true,
})

.constant('CognitoAuthS3Config', {
  BUCKET_REGION: 'eu-west-1',
  BUCKET_NAME: settings.bucketName,
  TRACE: true,
})

;
<|endoftext|>


<commit_before>'use strict'

let gulp = require('gulp')
let connect = require('gulp-connect')
let sourcemaps = require('gulp-sourcemaps')
let browserify = require('browserify')
let babelify = require('babelify')
let babel = require('gulp-babel')
let gutil = require('gulp-util')
let source = require('vinyl-source-stream')

function runBabelify(entries, output) {
  return browserify({
      entries: entries,
      extensions: ['.js', '.jsx'],
      paths: ['src/', 'node_modules/'],
    })
    .transform(babelify)
    .bundle()
    .on('error', err => {
      gutil.log(gutil.colors.red(err.message))
      this.emit('end')
    })
    .pipe(source(output.name))
    .pipe(gulp.dest(output.dir))
    .pipe(connect.reload())
}

gulp.task('serve', () => {
  connect.server({
    root: '.',
    livereload: true
  })
})

gulp.task('es6', () => {
  gulp.src(['src/list.jsx', 'src/list-item.jsx', 'src/index.js'])
    .pipe(babel())
    .pipe(gulp.dest('lib/'))
})

gulp.task('js', () => {
  return runBabelify('src/index.js', { name: 'list.js', dir: 'dist/' })
})

gulp.task('demo', () => {
  return runBabelify('src/demo.jsx', { name: 'demo.js', dir: 'dist/' })
})

gulp.task('watch', () => {
  gulp.watch(['src/*'], ['js'])
})

gulp.task('publish', ['js', 'es6'])
gulp.task('default', ['watch', 'demo', 'serve'])
<commit_msg>Remove es6 arrow functions from Gulpfile<commit_after>'use strict'

let gulp = require('gulp')
let connect = require('gulp-connect')
let sourcemaps = require('gulp-sourcemaps')
let browserify = require('browserify')
let babelify = require('babelify')
let babel = require('gulp-babel')
let gutil = require('gulp-util')
let source = require('vinyl-source-stream')

function runBabelify(entries, output) {
  return browserify({
      entries: entries,
      extensions: ['.js', '.jsx'],
      paths: ['src/', 'node_modules/'],
    })
    .transform(babelify)
    .bundle()
    .on('error', function(err) {
      gutil.log(gutil.colors.red(err.message))
      this.emit('end')
    })
    .pipe(source(output.name))
    .pipe(gulp.dest(output.dir))
    .pipe(connect.reload())
}

gulp.task('serve', function () {
  connect.server({
    root: '.',
    livereload: true
  })
})

gulp.task('es6', function () {
  gulp.src(['src/list.jsx', 'src/list-item.jsx', 'src/index.js'])
    .pipe(babel())
    .pipe(gulp.dest('lib/'))
})

gulp.task('js', function () {
  return runBabelify('src/index.js', { name: 'list.js', dir: 'dist/' })
})

gulp.task('demo', function () {
  return runBabelify('src/demo.jsx', { name: 'demo.js', dir: 'dist/' })
})

gulp.task('watch', function () {
  gulp.watch(['src/*'], ['js'])
})

gulp.task('publish', ['js', 'es6'])
gulp.task('default', ['watch', 'demo', 'serve'])
<|endoftext|>