<commit_before>import Ember from "ember"
import hbs from "htmlbars-inline-precompile"
import Standards from "../models/standards"
import diff from "npm:fast-json-patch"
import _ from "npm:lodash"
import listSorter from "../lib/positioned-list"
import uuid from "npm:node-uuid"
import Papa from "npm:papaparse"

let get = Ember.get
let set = Ember.set

export default Ember.Component.extend({
  orderedStandards: Ember.computed("standardsHash", function() {
    return Standards.hashToArray(this.get("standardsHash"))
  }),

  addStandard(depth, position, code, text, listId) {
    analytics.track("Editor - Add Standard")
    var id = uuid
      .v4()
      .replace(/-/g, "")
      .toUpperCase()
    var standard = {
      id: id,
      depth: depth,
      position: position,
      listId: listId || "",
      description: text || "",
      statementNotation: code || "",
    }
    this.get("standardsHash")[id] = standard
    this.notifyPropertyChange("standardsHash")
    Ember.run.scheduleOnce("afterRender", function() {
      $("[data-id=" + standard.id + "] .sortable-standard__list-id").focus()
    })
    this.validate()
    return standard
  },

  actions: {
    indent(standard) {
      analytics.track("Editor - Indent")
      Ember.set(standard, "depth", standard.depth + 1)
      this.notifyPropertyChange("standardsHash")
      this.validate()
    },

    outdent(standard) {
      if (standard.depth === 0) return
      analytics.track("Editor - Outdent")
      Ember.set(standard, "depth", standard.depth - 1)
      this.notifyPropertyChange("standardsHash")
      this.validate()
    },

    // find node above
    // find the node's last ancestorId and find the position of that item
    // increment it by 100 and apply to all the nodes from that point onward
    reorder(newArray, draggedItem) {
      let offset = $(`#sortable-item-${draggedItem.id}`).offset()
      let scrollTop = $(window).scrollTop()
      let relativePosition = offset.top - scrollTop

      analytics.track("Editor - Reorder")

      var oldIndex = _.indexOf(this.get("orderedStandards"), draggedItem)
      var itemsToMoveIds = [get(draggedItem, "id")]
      if (get(draggedItem, "ancestorIds")) {
        itemsToMoveIds = itemsToMoveIds.concat(get(draggedItem, "ancestorIds"))
      }

      var itemsToMove = _.map(itemsToMoveIds, id => get(this, `standardsHash.${id}`))

      // pull out the header item which is just null
      _.pull(newArray, null)
      var newIndex = _.indexOf(newArray, draggedItem)
      var itemAbove = newArray[newIndex - 1]
      var itemAboveIndex

      // index isn't 0, so we set it
      if (itemAbove) {
        let ids = [get(itemAbove, "id")]

        // if it's the same depth, we want the last of it's ancestors
        // as those are hidden in the UI
        if (itemAbove.depth === draggedItem.depth) {
          ids = _.compact(ids.concat(itemAbove.ancestorIds))
        }

        // look it up from the standardsHash
        itemAbove = get(this, `standardsHash.${_.last(ids)}`)

        itemAboveIndex = _.chain(get(this, "orderedStandards"))
          .reject(s => _.includes(itemsToMoveIds, get(s, "id")))
          .map(s => get(s, "id"))
          .indexOf(get(itemAbove, "id"))
          .value()
      } else {
        itemAboveIndex = -1
      }

      // Get the standards back with a new position
      var newStandards = listSorter.moveItemAndAncestors(get(this, "orderedStandards"), itemsToMove, itemAboveIndex)

      // Update from the new standards
      _.each(get(this, "standardsHash"), (value, key) => {
        set(get(this, "standardsHash"), key, get(newStandards, key))
      })

      // Change the iscollapsed status
      _.forEach(get(this, "standardsHash"), (s, id) => set(s, "isCollapsed", false))

      // Let ember know we changed the hash
      this.notifyPropertyChange("standardsHash")

      // Scroll to the old place
      Ember.run.scheduleOnce("afterRender", this, function() {
        let newOffset = $(`#sortable-item-${draggedItem.id}`).offset()
        $(window).scrollTop(newOffset.top - relativePosition)
      })
    },
    onEnterKey(item) {
      this.addStandard(item.depth, item.position + 1)
      return true
    },

    onArrow(direction, itemId, className) {
      let index = _.chain(get(this, "orderedStandards"))
        .map(s => get(s, "id"))
        .findIndex(s => s === itemId)
        .value()

      let addend
      if (direction === "up") addend = -1
      if (direction === "down") addend = +1
      let nextStandard = get(this, "orderedStandards").objectAt(index + addend)

      if (nextStandard) {
        $(`[data-id=${get(nextStandard, "id")}] .${className}`).focus()
      }
    },

    addStandard() {
      var depth = _.get(_.last(this.get("orderedStandards")), "depth", 0)
      var position = _.get(_.last(this.get("orderedStandards")), "position", 0) + 1000
      this.addStandard(depth, position)
    },

    removeStandard(id, index) {
      swal(
        {
          title: "Are you sure you want to delete this standard?",
          type: "warning",
          showCancelButton: true,
          confirmButtonColor: "#DD6B55",
          confirmButtonText: "Yes, delete it!",
          closeOnConfirm: false,
        },
        function() {
          analytics.track("Editor - Remove Standard")
          swal.close()
          delete this.get("standardsHash")[id]
          this.notifyPropertyChange("standardsHash")
          if (index) {
            Ember.run.scheduleOnce("afterRender", function() {
              var $el = $(".sortable-standard__list-id")[index]
              if ($el) $el.focus() // might be the last item, so check if it exists
            })
          }
        }.bind(this)
      )
      this.validate()
    },
    prepareMove(item) {
      // get offset
      let offset = $(`#sortable-item-${item.id}`).offset()
      let scrollTop = $(window).scrollTop()
      let relativePosition = offset.top - scrollTop

      // console.log('firstoffset', offset, scrollTop, offset.top-scrollTop)
      _.chain(get(this, "orderedStandards"))
        .filter(s => get(s, "depth") > get(item, "depth"))
        .forEach(s => set(s, "isCollapsed", true))
        .value()

      // Since we hid all the elements, we need to scroll to the right place on the screen.
      Ember.run.scheduleOnce("afterRender", this, function() {
        let newOffset = $(`#sortable-item-${item.id}`).offset()
        $(window).scrollTop(newOffset.top - relativePosition)
      })
    },

    uploadCSV(event) {
      let fileInput = $("#csv-upload")[0]
      let file = fileInput.files[0]
      Papa.parse(file, {
        header: true,
        complete: results => {
          _.map(results.data, result => {
            var position = _.get(_.last(this.get("orderedStandards")), "position", 0) + 1000
            var depth =
              result.depth !== "" && result.depth !== null && result.depth !== undefined ? parseInt(result.depth) : null
            this.addStandard(depth, position, result.code, result.text, result.outline)
          })
        },
      })
    },

    swapNotation() {
      let standards = get(this, "orderedStandards")
      _.each(standards, standard => {
        let newListId = standard.statementNotation
        let newStatementNotation = standard.listId
        set(standard, "listId", newListId)
        set(standard, "statementNotation", newStatementNotation)
      })
      return true
    },

    deleteAllStandards() {
      if (window.confirm("Are you sure you want to delete these?")){
        set(this, "standardsHash", {})
      }
    }
  },

  layout: hbs`

    {{#sortable-group tagName="div" onChange="reorder" onDragStart="onDragStart" as |group|}}
      {{! We need to wrap this as a sortable item so the sortable item handler
          knows to include it when it calculates absolute position}}
      {{#sortable-item tagName="div" group=group handle=".sortable-standard__handle"}}

Actions

Move, Ident, Outdent, Delete

Outline

E.g. I, II, III or A, B, C, etc

Standard

The text of the standard

Abbreviation

The shorthand identifier e.g. 1.NBT.4

      {{/sortable-item}}

      {{#each orderedStandards as |item index| }}
        {{sortable-standard
          group=group
          standards=standardsHash
          item=item
          index=index
          key=item.id
          onEnterKey=(action "onEnterKey" item)
          onArrow=(action "onArrow")
          removeStandard=(action "removeStandard" item.id index)
          prepareMove=(action "prepareMove" item)
          indent=(action "indent")
          outdent=(action "outdent")
        }}

      {{/each}}
    {{/sortable-group}}

{{partial "icons/ios7-add"}} Add a standard

    {{#if isCommitter}}

{{partial "icons/arrow-left"}} {{partial "icons/arrow-right"}}Swap Outline and Abbreviation

    {{/if}}

Import standards with a CSV

Instructions :

Go to this link and click "Make a copy"

Enter your standards

When you're done, click "File" -> "Download" -> "Comma-separated values"

Click the button below and select the file

      <input id="csv-upload" class="btn btn-primary btn-md" type="file" onchange={{action "uploadCSV" target=this}} style="display: none;">
      Upload CSV

      Danger! Click here to delete all standards and start over!

  `,
})
<commit_msg>Set depth to be 0 if not specified<commit_after>import Ember from "ember"
import hbs from "htmlbars-inline-precompile"
import Standards from "../models/standards"
import diff from "npm:fast-json-patch"
import _ from "npm:lodash"
import listSorter from "../lib/positioned-list"
import uuid from "npm:node-uuid"
import Papa from "npm:papaparse"

let get = Ember.get
let set = Ember.set

export default Ember.Component.extend({
  orderedStandards: Ember.computed("standardsHash", function() {
    return Standards.hashToArray(this.get("standardsHash"))
  }),

  addStandard(depth, position, code, text, listId) {
    analytics.track("Editor - Add Standard")
    var id = uuid
      .v4()
      .replace(/-/g, "")
      .toUpperCase()
    var standard = {
      id: id,
      depth: depth,
      position: position,
      listId: listId || "",
      description: text || "",
      statementNotation: code || "",
    }
    this.get("standardsHash")[id] = standard
    this.notifyPropertyChange("standardsHash")
    Ember.run.scheduleOnce("afterRender", function() {
      $("[data-id=" + standard.id + "] .sortable-standard__list-id").focus()
    })
    this.validate()
    return standard
  },

  actions: {
    indent(standard) {
      analytics.track("Editor - Indent")
      Ember.set(standard, "depth", standard.depth + 1)
      this.notifyPropertyChange("standardsHash")
      this.validate()
    },

    outdent(standard) {
      if (standard.depth === 0) return
      analytics.track("Editor - Outdent")
      Ember.set(standard, "depth", standard.depth - 1)
      this.notifyPropertyChange("standardsHash")
      this.validate()
    },

    // find node above
    // find the node's last ancestorId and find the position of that item
    // increment it by 100 and apply to all the nodes from that point onward
    reorder(newArray, draggedItem) {
      let offset = $(`#sortable-item-${draggedItem.id}`).offset()
      let scrollTop = $(window).scrollTop()
      let relativePosition = offset.top - scrollTop

      analytics.track("Editor - Reorder")

      var oldIndex = _.indexOf(this.get("orderedStandards"), draggedItem)
      var itemsToMoveIds = [get(draggedItem, "id")]
      if (get(draggedItem, "ancestorIds")) {
        itemsToMoveIds = itemsToMoveIds.concat(get(draggedItem, "ancestorIds"))
      }

      var itemsToMove = _.map(itemsToMoveIds, id => get(this, `standardsHash.${id}`))

      // pull out the header item which is just null
      _.pull(newArray, null)
      var newIndex = _.indexOf(newArray, draggedItem)
      var itemAbove = newArray[newIndex - 1]
      var itemAboveIndex

      // index isn't 0, so we set it
      if (itemAbove) {
        let ids = [get(itemAbove, "id")]

        // if it's the same depth, we want the last of it's ancestors
        // as those are hidden in the UI
        if (itemAbove.depth === draggedItem.depth) {
          ids = _.compact(ids.concat(itemAbove.ancestorIds))
        }

        // look it up from the standardsHash
        itemAbove = get(this, `standardsHash.${_.last(ids)}`)

        itemAboveIndex = _.chain(get(this, "orderedStandards"))
          .reject(s => _.includes(itemsToMoveIds, get(s, "id")))
          .map(s => get(s, "id"))
          .indexOf(get(itemAbove, "id"))
          .value()
      } else {
        itemAboveIndex = -1
      }

      // Get the standards back with a new position
      var newStandards = listSorter.moveItemAndAncestors(get(this, "orderedStandards"), itemsToMove, itemAboveIndex)

      // Update from the new standards
      _.each(get(this, "standardsHash"), (value, key) => {
        set(get(this, "standardsHash"), key, get(newStandards, key))
      })

      // Change the iscollapsed status
      _.forEach(get(this, "standardsHash"), (s, id) => set(s, "isCollapsed", false))

      // Let ember know we changed the hash
      this.notifyPropertyChange("standardsHash")

      // Scroll to the old place
      Ember.run.scheduleOnce("afterRender", this, function() {
        let newOffset = $(`#sortable-item-${draggedItem.id}`).offset()
        $(window).scrollTop(newOffset.top - relativePosition)
      })
    },
    onEnterKey(item) {
      this.addStandard(item.depth, item.position + 1)
      return true
    },

    onArrow(direction, itemId, className) {
      let index = _.chain(get(this, "orderedStandards"))
        .map(s => get(s, "id"))
        .findIndex(s => s === itemId)
        .value()

      let addend
      if (direction === "up") addend = -1
      if (direction === "down") addend = +1
      let nextStandard = get(this, "orderedStandards").objectAt(index + addend)

      if (nextStandard) {
        $(`[data-id=${get(nextStandard, "id")}] .${className}`).focus()
      }
    },

    addStandard() {
      var depth = _.get(_.last(this.get("orderedStandards")), "depth", 0)
      var position = _.get(_.last(this.get("orderedStandards")), "position", 0) + 1000
      this.addStandard(depth, position)
    },

    removeStandard(id, index) {
      swal(
        {
          title: "Are you sure you want to delete this standard?",
          type: "warning",
          showCancelButton: true,
          confirmButtonColor: "#DD6B55",
          confirmButtonText: "Yes, delete it!",
          closeOnConfirm: false,
        },
        function() {
          analytics.track("Editor - Remove Standard")
          swal.close()
          delete this.get("standardsHash")[id]
          this.notifyPropertyChange("standardsHash")
          if (index) {
            Ember.run.scheduleOnce("afterRender", function() {
              var $el = $(".sortable-standard__list-id")[index]
              if ($el) $el.focus() // might be the last item, so check if it exists
            })
          }
        }.bind(this)
      )
      this.validate()
    },
    prepareMove(item) {
      // get offset
      let offset = $(`#sortable-item-${item.id}`).offset()
      let scrollTop = $(window).scrollTop()
      let relativePosition = offset.top - scrollTop

      // console.log('firstoffset', offset, scrollTop, offset.top-scrollTop)
      _.chain(get(this, "orderedStandards"))
        .filter(s => get(s, "depth") > get(item, "depth"))
        .forEach(s => set(s, "isCollapsed", true))
        .value()

      // Since we hid all the elements, we need to scroll to the right place on the screen.
      Ember.run.scheduleOnce("afterRender", this, function() {
        let newOffset = $(`#sortable-item-${item.id}`).offset()
        $(window).scrollTop(newOffset.top - relativePosition)
      })
    },

    uploadCSV(event) {
      let fileInput = $("#csv-upload")[0]
      let file = fileInput.files[0]
      Papa.parse(file, {
        header: true,
        complete: results => {
          _.map(results.data, result => {
            var position = _.get(_.last(this.get("orderedStandards")), "position", 0) + 1000
            var depth =
              result.depth !== "" && result.depth !== null && result.depth !== undefined ? parseInt(result.depth) : 0
            this.addStandard(depth, position, result.code, result.text, result.outline)
          })
        },
      })
    },

    swapNotation() {
      let standards = get(this, "orderedStandards")
      _.each(standards, standard => {
        let newListId = standard.statementNotation
        let newStatementNotation = standard.listId
        set(standard, "listId", newListId)
        set(standard, "statementNotation", newStatementNotation)
      })
      return true
    },

    deleteAllStandards() {
      if (window.confirm("Are you sure you want to delete these?")){
        set(this, "standardsHash", {})
      }
    }
  },

  layout: hbs`

    {{#sortable-group tagName="div" onChange="reorder" onDragStart="onDragStart" as |group|}}
      {{! We need to wrap this as a sortable item so the sortable item handler
          knows to include it when it calculates absolute position}}
      {{#sortable-item tagName="div" group=group handle=".sortable-standard__handle"}}

Actions

Move, Ident, Outdent, Delete

Outline

E.g. I, II, III or A, B, C, etc

Standard

The text of the standard

Abbreviation

The shorthand identifier e.g. 1.NBT.4

      {{/sortable-item}}

      {{#each orderedStandards as |item index| }}
        {{sortable-standard
          group=group
          standards=standardsHash
          item=item
          index=index
          key=item.id
          onEnterKey=(action "onEnterKey" item)
          onArrow=(action "onArrow")
          removeStandard=(action "removeStandard" item.id index)
          prepareMove=(action "prepareMove" item)
          indent=(action "indent")
          outdent=(action "outdent")
        }}

      {{/each}}
    {{/sortable-group}}

{{partial "icons/ios7-add"}} Add a standard

    {{#if isCommitter}}

{{partial "icons/arrow-left"}} {{partial "icons/arrow-right"}}Swap Outline and Abbreviation

    {{/if}}

Import standards with a CSV

Instructions :

Go to this link and click "Make a copy"

Enter your standards

When you're done, click "File" -> "Download" -> "Comma-separated values"

Click the button below and select the file

      <input id="csv-upload" class="btn btn-primary btn-md" type="file" onchange={{action "uploadCSV" target=this}} style="display: none;">
      Upload CSV

      Danger! Click here to delete all standards and start over!

  `,
})
<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular.module('civic.sources')
    .directive('sourceSuggestionGrid', sourceSuggestionGrid)
    .controller('SourceSuggestionGridController', SourceSuggestionGridController);

  // @ngInject
  function sourceSuggestionGrid() {
    var directive = {
      restrict: 'E',
      replace: true,
      scope: {
        suggestions: '=',
        rows: '=',
        mode:'='
      },
      templateUrl: 'app/views/sources/components/sourceSuggestionGrid.tpl.html',
      controller: 'SourceSuggestionGridController'
    };
    return directive;
  }

  // @ngInject
  function SourceSuggestionGridController($scope,
                                $state,
                                uiGridConstants) {
    console.log('SourceSuggestionGridController Loaded.');

    var vm = $scope.vm = {};

    var mode = $scope.mode;

    vm.addEvidence = function(suggestion) {
      console.log('addEvidence called.');
      console.log(suggestion);
    };

    vm.rowsToShow = $scope.rows ? $scope.rows : 10;
    vm.sourceSuggestionGridOptions = {
      minRowsToShow: vm.rowsToShow - 1,
      //enablePaginationControls: true,
      //paginationPageSizes: [8],
      //paginationPageSize: 8,
      enablePaging: false,

      enableHorizontalScrollbar: uiGridConstants.scrollbars.NEVER,
      enableVerticalScrollbar: uiGridConstants.scrollbars.NEVER,
      enableFiltering: true,
      enableColumnMenus: false,
      enableSorting: true,
      enableRowHeaderSelection: false,
      multiSelect: false,
      modifierKeysToMultiSelect: false,
      noUnselect: true,
      columnDefs: [
        {
          name: 'status',
          displayName: 'Status',
          enableFiltering: true,
          allowCellFocus: false,
          type: 'string',
          width: '5%',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'submitter',
          displayName: 'Submitter',
          enableFiltering: true,
          allowCellFocus: false,
          type: 'string',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          },
          cellTemplate: '
<user-block user="row.entity[col.field]"
',
        },
        {
          name: 'pubmed_id',
          displayName: 'Pubmed ID',
          visible: mode === 'full',
          enableFiltering: true,
          allowCellFocus: false,
          type: 'string',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },

        {
          name: 'author_list_string',
          displayName: 'Authors',
          visible: mode === 'full',
          enableFiltering: true,
          allowCellFocus: false,
          type: 'string',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'publication_date_string',
          displayName: 'Date',
          visible: mode === 'full',
          type: 'string',
          enableFiltering: true,
          allowCellFocus: false
        },
        {
          name: 'full_journal_title',
          displayName: 'Journal',
          visible: mode === 'full',
          type: 'string',
          enableFiltering: true,
          allowCellFocus: false
        },
        {
          name: 'abstract',
          displayName: 'Abstract',
          visible: mode === 'full',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'gene',
          displayName: 'Gene',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'variant',
          displayName: 'Variant',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'disease',
          displayName: 'Disease',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'initial_comment',
          displayName: 'Comment',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          cellTemplate: 'app/views/events/common/geneGrid/tooltipCell.tpl.html',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'action',
          displayName: '',
          allowCellFocus: false,
          enableFiltering: false,
          width: '5%',
          cellTemplate: '
Add
'
        }
      ]
    };

    vm.sourceSuggestionGridOptions.onRegisterApi = function (gridApi) {
      var suggestions = $scope.suggestions;
      vm.gridApi = gridApi;

      vm.context = $scope.context;
      vm.sourceSuggestionGridOptions.data = prepSuggestions(suggestions);

      $scope.$watchCollection('suggestions', function (suggestions) {
        vm.sourceSuggestionGridOptions.minRowsToShow = suggestions.length + 1;
        vm.sourceSuggestionGridOptions.data = prepSuggestions(suggestions);
      });

      function prepSuggestions(suggestions) {
        return _.map(suggestions, function(source) {
          var urlBase = '#/add/evidence/basic';
          var urlElements = [];
          if(_.has(source, 'gene')) {
            urlElements.push('geneName=' + source.gene);
          }
          if(_.has(source, 'variant')) {
            urlElements.push('variantName=' + source.variant);
          }
          if(_.has(source, 'disease')) {
            urlElements.push('diseaseName=' + source.disease);
          }
          if(_.has(source, 'pubmed_id')) {
            urlElements.push('pubmedId=' + source.pubmed_id);
          }

          urlElements.push('sourceSuggestionId=' + source.id);
          source.addEvidenceUrl = urlBase + '?' + urlElements.join('&') + '&' + 'suggestionId=' + source.id;
          return source;
        });
      }
    };
  }

})();
<commit_msg>'add' button on source suggestion grid disabled for curated and rejected suggestions<commit_after>(function() {
  'use strict';

  angular.module('civic.sources')
    .directive('sourceSuggestionGrid', sourceSuggestionGrid)
    .controller('SourceSuggestionGridController', SourceSuggestionGridController);

  // @ngInject
  function sourceSuggestionGrid() {
    var directive = {
      restrict: 'E',
      replace: true,
      scope: {
        suggestions: '=',
        rows: '=',
        mode:'='
      },
      templateUrl: 'app/views/sources/components/sourceSuggestionGrid.tpl.html',
      controller: 'SourceSuggestionGridController'
    };
    return directive;
  }

  // @ngInject
  function SourceSuggestionGridController($scope,
                                $state,
                                uiGridConstants) {
    console.log('SourceSuggestionGridController Loaded.');

    var vm = $scope.vm = {};

    var mode = $scope.mode;

    vm.addEvidence = function(suggestion) {
      console.log('addEvidence called.');
      console.log(suggestion);
    };

    vm.rowsToShow = $scope.rows ? $scope.rows : 10;
    vm.sourceSuggestionGridOptions = {
      minRowsToShow: vm.rowsToShow - 1,
      //enablePaginationControls: true,
      //paginationPageSizes: [8],
      //paginationPageSize: 8,
      enablePaging: false,

      enableHorizontalScrollbar: uiGridConstants.scrollbars.NEVER,
      enableVerticalScrollbar: uiGridConstants.scrollbars.NEVER,
      enableFiltering: true,
      enableColumnMenus: false,
      enableSorting: true,
      enableRowHeaderSelection: false,
      multiSelect: false,
      modifierKeysToMultiSelect: false,
      noUnselect: true,
      columnDefs: [
        {
          name: 'status',
          displayName: 'Status',
          enableFiltering: true,
          allowCellFocus: false,
          type: 'string',
          width: '8%',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'submitter',
          displayName: 'Submitter',
          enableFiltering: true,
          allowCellFocus: false,
          type: 'string',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          },
          cellTemplate: '
<user-block user="row.entity[col.field]"
',
        },
        {
          name: 'pubmed_id',
          displayName: 'Pubmed ID',
          visible: mode === 'full',
          enableFiltering: true,
          allowCellFocus: false,
          type: 'string',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },

        {
          name: 'author_list_string',
          displayName: 'Authors',
          visible: mode === 'full',
          enableFiltering: true,
          allowCellFocus: false,
          type: 'string',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'publication_date_string',
          displayName: 'Date',
          visible: mode === 'full',
          type: 'string',
          enableFiltering: true,
          allowCellFocus: false
        },
        {
          name: 'full_journal_title',
          displayName: 'Journal',
          visible: mode === 'full',
          type: 'string',
          enableFiltering: true,
          allowCellFocus: false
        },
        {
          name: 'abstract',
          displayName: 'Abstract',
          visible: mode === 'full',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'gene',
          displayName: 'Gene',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'variant',
          displayName: 'Variant',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'disease',
          displayName: 'Disease',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'initial_comment',
          displayName: 'Comment',
          type: 'string',
          allowCellFocus: false,
          enableFiltering: true,
          cellTemplate: 'app/views/events/common/geneGrid/tooltipCell.tpl.html',
          filter: {
            condition: uiGridConstants.filter.CONTAINS
          }
        },
        {
          name: 'action',
          displayName: '',
          allowCellFocus: false,
          enableFiltering: false,
          width: '5%',
          cellTemplate: '
Add
'
        }
      ]
    };

    vm.sourceSuggestionGridOptions.onRegisterApi = function (gridApi) {
      var suggestions = $scope.suggestions;
      vm.gridApi = gridApi;

      vm.context = $scope.context;
      vm.sourceSuggestionGridOptions.data = prepSuggestions(suggestions);

      $scope.$watchCollection('suggestions', function (suggestions) {
        vm.sourceSuggestionGridOptions.minRowsToShow = suggestions.length + 1;
        vm.sourceSuggestionGridOptions.data = prepSuggestions(suggestions);
      });

      function prepSuggestions(suggestions) {
        return _.map(suggestions, function(source) {
          var urlBase = '#/add/evidence/basic';
          var urlElements = [];
          if(_.has(source, 'gene')) {
            urlElements.push('geneName=' + source.gene);
          }
          if(_.has(source, 'variant')) {
            urlElements.push('variantName=' + source.variant);
          }
          if(_.has(source, 'disease')) {
            urlElements.push('diseaseName=' + source.disease);
          }
          if(_.has(source, 'pubmed_id')) {
            urlElements.push('pubmedId=' + source.pubmed_id);
          }

          urlElements.push('sourceSuggestionId=' + source.id);
          source.addEvidenceUrl = urlBase + '?' + urlElements.join('&') + '&' + 'suggestionId=' + source.id;
          return source;
        });
      }
    };
  }

})();
<|endoftext|>


<commit_before>import React from 'react';
import PusherStore from '../../stores/PusherStore';
import classNames from 'classnames';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

class NewChangelogsBadge extends React.Component {
  static propTypes = {
    className: React.PropTypes.string,
    style: React.PropTypes.object,
    viewer: React.PropTypes.shape({
      unreadChangelogs: React.PropTypes.shape({
        count: React.PropTypes.number
      })
    })
  };

  state = {
    unreadChangelogsCount: this.props.viewer.unreadChangelogs ? this.props.viewer.unreadChangelogs.count : 0
  };

  componentDidMount() {
    PusherStore.on("user_stats:change", this.handlePusherWebsocketEvent);
  }

  componentWillUnmount() {
    PusherStore.off("user_stats:change", this.handlePusherWebsocketEvent);
  }

  handlePusherWebsocketEvent = (payload) => {
    this.setState({ unreadChangelogsCount: payload.unreadChangelogsCount });
  };

  componentWillReceiveProps = (nextProps) => {
    if (nextProps.viewer.unreadChangelogs) {
      this.setState({ unreadChangelogsCount: nextProps.viewer.unreadChangelogs.count });
    }
  }

  shouldComponentUpdate = (nextProps, nextState) => {
    const { unreadChangeLogsCount: lastChangeLogsCount } = this.state;

    const { unreadChangeLogsCount: newChangeLogsCount } = nextState;
    const { unreadChangelogs: newUnreadChangelogs } = nextProps.viewer;

    return (
      (newUnreadChangelogs && newUnreadChangelogs.count !== lastChangeLogsCount)
      || (newChangeLogsCount !== lastChangeLogsCount)
    );
  };

  render() {
    if (this.state.unreadChangelogsCount > 0) {
      return (
        <ReactCSSTransitionGroup transitionName="transition-changelog-appear" transitionAppear={true} transitionAppearTimeout={3000} transitionEnterTimeout={5000} transitionLeaveTimeout={5000}>

            NEW

        </ReactCSSTransitionGroup>
      );
    } else {
      return null;
    }
  }
}

export default NewChangelogsBadge;
<commit_msg>Use CachedStateWrapper on NewChangelogsBadge<commit_after>import React from 'react';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import classNames from 'classnames';

import PusherStore from '../../stores/PusherStore';
import CachedStateWrapper from '../../helpers/CachedStateWrapper';

class NewChangelogsBadge extends React.Component {
  static propTypes = {
    className: React.PropTypes.string,
    style: React.PropTypes.object,
    viewer: React.PropTypes.shape({
      unreadChangelogs: React.PropTypes.shape({
        count: React.PropTypes.number
      })
    })
  };

  state = {
    unreadChangelogsCount: this.props.viewer.unreadChangelogs ? this.props.viewer.unreadChangelogs.count : 0
  };

  componentWillMount() {
    if (!this.props.viewer.unreadChangelogs) {
      this.setState({
        unreadChangelogsCount: this.getCachedState().unreadChangelogsCount || 0
      });
    }
  }

  componentDidMount() {
    PusherStore.on("user_stats:change", this.handlePusherWebsocketEvent);
  }

  componentWillUnmount() {
    PusherStore.off("user_stats:change", this.handlePusherWebsocketEvent);
  }

  handlePusherWebsocketEvent = (payload) => {
    this.setCachedState({ unreadChangelogsCount: payload.unreadChangelogsCount });
  };

  componentWillReceiveProps = (nextProps) => {
    if (nextProps.viewer.unreadChangelogs) {
      this.setCachedState({ unreadChangelogsCount: nextProps.viewer.unreadChangelogs.count });
    }
  }

  shouldComponentUpdate = (nextProps, nextState) => {
    const { unreadChangeLogsCount: lastChangeLogsCount } = this.state;

    const { unreadChangeLogsCount: newChangeLogsCount } = nextState;
    const { unreadChangelogs: newUnreadChangelogs } = nextProps.viewer;

    return (
      (newUnreadChangelogs && newUnreadChangelogs.count !== lastChangeLogsCount)
      || (newChangeLogsCount !== lastChangeLogsCount)
    );
  };

  render() {
    if (this.state.unreadChangelogsCount > 0) {
      return (
        <ReactCSSTransitionGroup transitionName="transition-changelog-appear" transitionAppear={true} transitionAppearTimeout={3000} transitionEnterTimeout={5000} transitionLeaveTimeout={5000}>

            NEW

        </ReactCSSTransitionGroup>
      );
    } else {
      return null;
    }
  }
}

export default CachedStateWrapper(NewChangelogsBadge);
<|endoftext|>


<commit_before>import React from 'react';
import classNames from 'classnames';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

class NewChangelogsBadge extends React.Component {
  static propTypes = {
    className: React.PropTypes.string,
    style: React.PropTypes.object,
    viewer: React.PropTypes.shape({
      unreadChangelogs: React.PropTypes.shape({
        count: React.PropTypes.integer
      })
    })
  };

  state = {
    unreadChangelogsCount: this.props.viewer.unreadChangelogs.count
  };

  componentDidMount() {
    PusherStore.on("user_stats:change", this._onStoreChange.bind(this));
  }

  componentWillUnmount() {
    PusherStore.off("user_stats:change", this._onStoreChange.bind(this));
  }

  render() {
    if(this.state.unreadChangelogsCount > 0) {
      return (
        <ReactCSSTransitionGroup transitionName="transition-changelog-appear" transitionAppear transitionAppearTimeout={3000} transitionEnterTimeout={5000} transitionLeaveTimeout={5000}>

            NEW

        </ReactCSSTransitionGroup>
      );
    } else {
      return null;
    }
  }

  _onStoreChange(payload) {
    this.setState({ unreadChangelogsCount: payload.unreadChangelogsCount });
  }
}

export default NewChangelogsBadge;
<commit_msg>Fix PusherStore<commit_after>import React from 'react';
import PusherStore from '../../stores/PusherStore';
import classNames from 'classnames';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

class NewChangelogsBadge extends React.Component {
  static propTypes = {
    className: React.PropTypes.string,
    style: React.PropTypes.object,
    viewer: React.PropTypes.shape({
      unreadChangelogs: React.PropTypes.shape({
        count: React.PropTypes.integer
      })
    })
  };

  state = {
    unreadChangelogsCount: this.props.viewer.unreadChangelogs.count
  };

  componentDidMount() {
    PusherStore.on("user_stats:change", this._onStoreChange.bind(this));
  }

  componentWillUnmount() {
    PusherStore.off("user_stats:change", this._onStoreChange.bind(this));
  }

  render() {
    if(this.state.unreadChangelogsCount > 0) {
      return (
        <ReactCSSTransitionGroup transitionName="transition-changelog-appear" transitionAppear transitionAppearTimeout={3000} transitionEnterTimeout={5000} transitionLeaveTimeout={5000}>

            NEW

        </ReactCSSTransitionGroup>
      );
    } else {
      return null;
    }
  }

  _onStoreChange(payload) {
    this.setState({ unreadChangelogsCount: payload.unreadChangelogsCount });
  }
}

export default NewChangelogsBadge;
<|endoftext|>


<commit_before>import React, { Component } from "react";
import { autobind } from "core-decorators";
import { substruct, compose, eq, get } from "../../../fp";
import service from "../../../connectors/service";
import ticketsPage from "../../../connectors/ticketsPage";
import ErrorScreen from "../../ErrorScreen";
import TicketsPage from "./Page";
import { FormattedMessage as T } from "react-intl";

@autobind
class Tickets extends Component {
  constructor(props) {
    super(props);
    this.state = this.getInitialState();
  }

  getInitialState() {
    return {
      account: this.props.defaultSpendingAccount,
      stakePool: this.props.defaultStakePool,
      passphraseHeading: null,
      passphraseDescription: null,
      passphraseCallback: null,
      isShowingTicketsInfo: false,
      isShowingStakePools: !this.props.defaultStakePool,
      isShowingVotingPrefs: false,
      isShowingImportScript: false,
      isRequestingPassphrase: false
    };
  }

  componentWillMount() {
    this.props.onClearStakePoolConfigError();
    this.props.onClearStakePoolConfigSuccess();
    this.props.onClearPurchaseTicketsSuccess();
    this.props.onClearPurchaseTicketsError();
    this.props.onClearRevokeTicketsSuccess();
    this.props.onClearRevokeTicketsError();
    this.props.onClearImportScriptSuccess();
    this.props.onClearImportScriptError();
    this.props.onClearStartAutoBuyerSuccess();
    this.props.onClearStartAutoBuyerError();
    this.props.onClearStopAutoBuyerSuccess();
    this.props.onClearStopAutoBuyerError();
  }

  componentWillReceiveProps(nextProps) {
    if (!this.state.stakePool && nextProps.defaultStakePool) {
      // Added first stake pool
      this.setState({
        stakePool: nextProps.defaultStakePool,
        isShowingStakePools: false
      });
    }
  }

  render() {
    return (!this.props.walletService || !this.props.ticketBuyerService) ? <ErrorScreen /> : (
      <TicketsPage
        {...{
          ...this.props,
          ...this.state,
          stakePool: this.getStakePool(),
          account: this.getAccount(),
          ...substruct({
            onShowTicketsInfo: null,
            onHideTicketsInfo: null,
            onChangeStakePool: null,
            onChangeAccount: null,
            onShowImportScript: null,
            onShowRevokeTicket: null,
            onRequestPassphrase: null,
            onCancelPassphraseRequest: null,
            onCancelImportScript: null,
            onToggleTicketStakePool: null,
            onShowStakePoolConfig: null,
            onHideStakePoolConfig: null,
            onImportScript: null
          }, this)
        }}
      />
    );
  }

  onToggleTicketStakePool(side) {
    this.setState({
      isShowingVotingPrefs: (side === "right") ? true : false,
      purchaseTicketsStakePoolConfig: false
    });
  }

  getStakePool() {
    const pool = this.props.onChangeStakePool ? this.props.stakePool : this.state.stakePool;
    return pool
      ? this.props.configuredStakePools.find(compose(eq(pool.Host), get("Host")))
      : null;
  }

  getAccount() {
    const account = this.props.onChangeAccount ? this.props.account : this.state.account;
    return this.props.spendingAccounts.find(compose(eq(account.value), get("value")));
  }

  onChangeStakePool(stakePool) {
    const { onChangeStakePool } = this.props;
    this.setState({ stakePool });
    onChangeStakePool && onChangeStakePool(stakePool);
  }

  onChangeAccount(account) {
    const { onChangeAccount } = this.props;
    this.setState({ account });
    onChangeAccount && onChangeAccount(account);
  }

  onImportScript(privpass, script) {
    const { onImportScript } = this.props;
    onImportScript && onImportScript(privpass, script, true, 0, null);
    this.setState({ isShowingImportScript: false });
  }

  onRevokeTickets(privpass) {
    const { onRevokeTickets } = this.props;
    onRevokeTickets && onRevokeTickets(privpass);
    this.onCancelPassphraseRequest();
  }

  onCancelPassphraseRequest() {
    this.setState({
      isRequestingPassphrase: false,
      passphraseHeading: null,
      passphraseDescription: null,
      passphraseCallback: null
    });
  }

  onShowTicketsInfo() {
    this.setState({ isShowingTicketsInfo: true });
  }

  onHideTicketsInfo() {
    this.setState({ isShowingTicketsInfo: false });
  }

  onShowStakePoolConfig() {
    this.setState({ isShowingStakePools: true });
  }

  onHideStakePoolConfig() {
    this.setState({ isShowingStakePools: false });
  }

  onRequestPassphrase(passphraseHeading, passphraseDescription, passphraseCallback) {
    this.setState({
      passphraseHeading,
      passphraseDescription,
      passphraseCallback,
      isRequestingPassphrase: true
    });
  }

  onShowImportScript() {
    this.setState({ isShowingImportScript: true });
  }

  onShowRevokeTicket() {
    this.onRequestPassphrase(
      <T id="stake.revokeTicketsPassphrase" m="Enter Passphrase to Revoke Tickets" />,
      null, this.onRevokeTickets);
  }

  onCancelImportScript() {
    this.setState({ isShowingImportScript: false });
  }
}

export default service(ticketsPage(Tickets));
<commit_msg>tooltip rebuild needed in componentDidUpdate() (#768)<commit_after>import React, { Component } from "react";
import { autobind } from "core-decorators";
import { substruct, compose, eq, get } from "../../../fp";
import service from "../../../connectors/service";
import ticketsPage from "../../../connectors/ticketsPage";
import ErrorScreen from "../../ErrorScreen";
import TicketsPage from "./Page";
import { FormattedMessage as T } from "react-intl";
import ReactToolTip from "react-tooltip";

@autobind
class Tickets extends Component {
  constructor(props) {
    super(props);
    this.state = this.getInitialState();
  }

  getInitialState() {
    return {
      account: this.props.defaultSpendingAccount,
      stakePool: this.props.defaultStakePool,
      passphraseHeading: null,
      passphraseDescription: null,
      passphraseCallback: null,
      isShowingTicketsInfo: false,
      isShowingStakePools: !this.props.defaultStakePool,
      isShowingVotingPrefs: false,
      isShowingImportScript: false,
      isRequestingPassphrase: false
    };
  }

  componentWillMount() {
    this.props.onClearStakePoolConfigError();
    this.props.onClearStakePoolConfigSuccess();
    this.props.onClearPurchaseTicketsSuccess();
    this.props.onClearPurchaseTicketsError();
    this.props.onClearRevokeTicketsSuccess();
    this.props.onClearRevokeTicketsError();
    this.props.onClearImportScriptSuccess();
    this.props.onClearImportScriptError();
    this.props.onClearStartAutoBuyerSuccess();
    this.props.onClearStartAutoBuyerError();
    this.props.onClearStopAutoBuyerSuccess();
    this.props.onClearStopAutoBuyerError();
  }

  componentWillReceiveProps(nextProps) {
    if (!this.state.stakePool && nextProps.defaultStakePool) {
      // Added first stake pool
      this.setState({
        stakePool: nextProps.defaultStakePool,
        isShowingStakePools: false
      });
    }
  }

  componentDidUpdate (prevProps, prevState) {
    if (prevState != this.state) {
      ReactToolTip.rebuild();
    }
  }

  render() {
    return (!this.props.walletService || !this.props.ticketBuyerService) ? <ErrorScreen /> : (
      <TicketsPage
        {...{
          ...this.props,
          ...this.state,
          stakePool: this.getStakePool(),
          account: this.getAccount(),
          ...substruct({
            onShowTicketsInfo: null,
            onHideTicketsInfo: null,
            onChangeStakePool: null,
            onChangeAccount: null,
            onShowImportScript: null,
            onShowRevokeTicket: null,
            onRequestPassphrase: null,
            onCancelPassphraseRequest: null,
            onCancelImportScript: null,
            onToggleTicketStakePool: null,
            onShowStakePoolConfig: null,
            onHideStakePoolConfig: null,
            onImportScript: null
          }, this)
        }}
      />
    );
  }

  onToggleTicketStakePool(side) {
    this.setState({
      isShowingVotingPrefs: (side === "right") ? true : false,
      purchaseTicketsStakePoolConfig: false
    });
  }

  getStakePool() {
    const pool = this.props.onChangeStakePool ? this.props.stakePool : this.state.stakePool;
    return pool
      ? this.props.configuredStakePools.find(compose(eq(pool.Host), get("Host")))
      : null;
  }

  getAccount() {
    const account = this.props.onChangeAccount ? this.props.account : this.state.account;
    return this.props.spendingAccounts.find(compose(eq(account.value), get("value")));
  }

  onChangeStakePool(stakePool) {
    const { onChangeStakePool } = this.props;
    this.setState({ stakePool });
    onChangeStakePool && onChangeStakePool(stakePool);
  }

  onChangeAccount(account) {
    const { onChangeAccount } = this.props;
    this.setState({ account });
    onChangeAccount && onChangeAccount(account);
  }

  onImportScript(privpass, script) {
    const { onImportScript } = this.props;
    onImportScript && onImportScript(privpass, script, true, 0, null);
    this.setState({ isShowingImportScript: false });
  }

  onRevokeTickets(privpass) {
    const { onRevokeTickets } = this.props;
    onRevokeTickets && onRevokeTickets(privpass);
    this.onCancelPassphraseRequest();
  }

  onCancelPassphraseRequest() {
    this.setState({
      isRequestingPassphrase: false,
      passphraseHeading: null,
      passphraseDescription: null,
      passphraseCallback: null
    });
  }

  onShowTicketsInfo() {
    this.setState({ isShowingTicketsInfo: true });
  }

  onHideTicketsInfo() {
    this.setState({ isShowingTicketsInfo: false });
  }

  onShowStakePoolConfig() {
    this.setState({ isShowingStakePools: true });
  }

  onHideStakePoolConfig() {
    this.setState({ isShowingStakePools: false });
  }

  onRequestPassphrase(passphraseHeading, passphraseDescription, passphraseCallback) {
    this.setState({
      passphraseHeading,
      passphraseDescription,
      passphraseCallback,
      isRequestingPassphrase: true
    });
  }

  onShowImportScript() {
    this.setState({ isShowingImportScript: true });
  }

  onShowRevokeTicket() {
    this.onRequestPassphrase(
      <T id="stake.revokeTicketsPassphrase" m="Enter Passphrase to Revoke Tickets" />,
      null, this.onRevokeTickets);
  }

  onCancelImportScript() {
    this.setState({ isShowingImportScript: false });
  }
}

export default service(ticketsPage(Tickets));
<|endoftext|>


<commit_before>import $          from 'blingblingjs'
import hotkeys    from 'hotkeys-js'

import {
  Handles, Label, Overlay, Gridlines, Corners,
  Hotkeys, Metatip, Ally, Distance, BoxModel, Grip
} from '../'

import {
  Selectable, Moveable, Padding, Margin, EditText, Font,
  Flex, Search, ColorPicker, BoxShadow, HueShift, MetaTip,
  Guides, Screenshot, Position, Accessibility, draggable
} from '../../features/'

import { VisBugStyles }           from '../styles.store'
import { VisBugModel }            from './model'
import * as Icons                 from './vis-bug.icons'
import { provideSelectorEngine }  from '../../features/search'
import { metaKey }                from '../../utilities/'
import { PluginRegistry }         from '../../plugins/_registry'

const modemap = {
  'hex':  'toHexString',
  'hsla': 'toHslString',
  'rgba': 'toRgbString',
}

export default class VisBug extends HTMLElement {
  constructor() {
    super()

    this.toolbar_model  = VisBugModel
    this._tutsBaseURL   = 'tuts' // can be set by content script
    this.$shadow        = this.attachShadow({mode: 'closed'})
  }

  connectedCallback() {
    this.$shadow.adoptedStyleSheets = [VisBugStyles]

    if (!this.$shadow.innerHTML)
      this.setup()

    this.selectorEngine = Selectable(this)
    this.colorPicker    = ColorPicker(this.$shadow, this.selectorEngine)

    provideSelectorEngine(this.selectorEngine)

    this.toolSelected($('[data-tool="guides"]', this.$shadow)[0])
  }

  disconnectedCallback() {
    this.deactivate_feature()
    this.cleanup()
    this.selectorEngine.disconnect()
    hotkeys.unbind(
      Object.keys(this.toolbar_model).reduce((events, key) =>
        events += ',' + key, ''))
    hotkeys.unbind(`${metaKey}+/`)
  }

  setup() {
    this.$shadow.innerHTML = this.render()
    this._colormode = modemap['hsla']

    $('li[data-tool]', this.$shadow).on('click', e =>
      this.toolSelected(e.currentTarget) && e.stopPropagation())

    draggable({
      el:this,
      surface: this.$shadow.querySelector('ol:not([colors])'),
      cursor: 'grab',
    })

    Object.entries(this.toolbar_model).forEach(([key, value]) =>
      hotkeys(key, e => {
        e.preventDefault()
        this.toolSelected(
          $(`[data-tool="${value.tool}"]`, this.$shadow)[0]
        )
      })
    )

    hotkeys(`${metaKey}+/,${metaKey}+.`, e =>
      this.$shadow.host.style.display =
        this.$shadow.host.style.display === 'none'
          ? 'block'
          : 'none')
  }

  cleanup() {
    const bye = [
      ...document.getElementsByTagName('visbug-hover'),
      ...document.getElementsByTagName('visbug-handles'),
      ...document.getElementsByTagName('visbug-label'),
      ...document.getElementsByTagName('visbug-gridlines'),
    ].forEach(el => el.remove())

    this.teardown();

    document.querySelectorAll('[data-pseudo-select=true]')
      .forEach(el =>
        el.removeAttribute('data-pseudo-select'))
  }

  toolSelected(el) {
    if (typeof el === 'string')
      el = $(`[data-tool="${el}"]`, this.$shadow)[0]

    if (this.active_tool && this.active_tool.dataset.tool === el.dataset.tool) return

    if (this.active_tool) {
      this.active_tool.attr('data-active', null)
      this.deactivate_feature()
    }

    el.attr('data-active', true)
    this.active_tool = el
    this[el.dataset.tool]()
  }

  render() {
    return `
      <visbug-hotkeys></visbug-hotkeys>

        ${Object.entries(this.toolbar_model).reduce((list, [key, tool]) => `
          ${list}

            ${tool.icon}
            ${this.demoTip({key, ...tool})}

        `,'')}

          <input type="color" value="">
          ${Icons.color_text}

          <input type="color" value="">
          ${Icons.color_background}

          <input type="color" value="">
          ${Icons.color_border}

    `
  }

  demoTip({key, tool, label, description, instruction}) {
    return `

              ${label}
              ${key}

${description}

            ${instruction}

    `
  }

  move() {
    this.deactivate_feature = Moveable(this.selectorEngine)
  }

  margin() {
    this.deactivate_feature = Margin(this.selectorEngine)
  }

  padding() {
    this.deactivate_feature = Padding(this.selectorEngine)
  }

  font() {
    this.deactivate_feature = Font(this.selectorEngine)
  }

  text() {
    this.selectorEngine.onSelectedUpdate(EditText)
    this.deactivate_feature = () =>
      this.selectorEngine.removeSelectedCallback(EditText)
  }

  align() {
    this.deactivate_feature = Flex(this.selectorEngine)
  }

  search() {
    this.deactivate_feature = Search($('[data-tool="search"]', this.$shadow))
  }

  boxshadow() {
    this.deactivate_feature = BoxShadow(this.selectorEngine)
  }

  hueshift() {
    this.deactivate_feature = HueShift({
      Color:  this.colorPicker,
      Visbug: this.selectorEngine,
    })
  }

  inspector() {
    this.deactivate_feature = MetaTip(this.selectorEngine)
  }

  accessibility() {
    this.deactivate_feature = Accessibility(this.selectorEngine)
  }

  guides() {
    this.deactivate_feature = Guides(this.selectorEngine)
  }

  screenshot() {
    this.deactivate_feature = Screenshot()
  }

  position() {
    let feature = Position()
    this.selectorEngine.onSelectedUpdate(feature.onNodesSelected)
    this.deactivate_feature = () => {
      this.selectorEngine.removeSelectedCallback(feature.onNodesSelected)
      feature.disconnect()
    }
  }

  execCommand(command) {
    const query = `/${command}`

    if (PluginRegistry.has(query))
      return PluginRegistry.get(query)({
        selected: this.selectorEngine.selection(),
        query
      })

    return Promise.resolve(new Error("Query not found"))
  }

  get activeTool() {
    return this.active_tool.dataset.tool
  }

  set tutsBaseURL(url) {
    this._tutsBaseURL = url
    this.setup()
  }

  set colorMode(mode) {
    this._colormode = modemap[mode]
  }

  get colorMode() {
    return this._colormode
  }
}

customElements.define('vis-bug', VisBug)
<commit_msg>cleaner hunt and destroy of visbug children<commit_after>import $          from 'blingblingjs'
import hotkeys    from 'hotkeys-js'

import {
  Handles, Label, Overlay, Gridlines, Corners,
  Hotkeys, Metatip, Ally, Distance, BoxModel, Grip
} from '../'

import {
  Selectable, Moveable, Padding, Margin, EditText, Font,
  Flex, Search, ColorPicker, BoxShadow, HueShift, MetaTip,
  Guides, Screenshot, Position, Accessibility, draggable
} from '../../features/'

import { VisBugStyles }           from '../styles.store'
import { VisBugModel }            from './model'
import * as Icons                 from './vis-bug.icons'
import { provideSelectorEngine }  from '../../features/search'
import { metaKey }                from '../../utilities/'
import { PluginRegistry }         from '../../plugins/_registry'

const modemap = {
  'hex':  'toHexString',
  'hsla': 'toHslString',
  'rgba': 'toRgbString',
}

export default class VisBug extends HTMLElement {
  constructor() {
    super()

    this.toolbar_model  = VisBugModel
    this._tutsBaseURL   = 'tuts' // can be set by content script
    this.$shadow        = this.attachShadow({mode: 'closed'})
  }

  connectedCallback() {
    this.$shadow.adoptedStyleSheets = [VisBugStyles]

    if (!this.$shadow.innerHTML)
      this.setup()

    this.selectorEngine = Selectable(this)
    this.colorPicker    = ColorPicker(this.$shadow, this.selectorEngine)

    provideSelectorEngine(this.selectorEngine)

    this.toolSelected($('[data-tool="guides"]', this.$shadow)[0])
  }

  disconnectedCallback() {
    this.deactivate_feature()
    this.cleanup()
    this.selectorEngine.disconnect()
    hotkeys.unbind(
      Object.keys(this.toolbar_model).reduce((events, key) =>
        events += ',' + key, ''))
    hotkeys.unbind(`${metaKey}+/`)
  }

  setup() {
    this.$shadow.innerHTML = this.render()
    this._colormode = modemap['hsla']

    $('li[data-tool]', this.$shadow).on('click', e =>
      this.toolSelected(e.currentTarget) && e.stopPropagation())

    draggable({
      el:this,
      surface: this.$shadow.querySelector('ol:not([colors])'),
      cursor: 'grab',
    })

    Object.entries(this.toolbar_model).forEach(([key, value]) =>
      hotkeys(key, e => {
        e.preventDefault()
        this.toolSelected(
          $(`[data-tool="${value.tool}"]`, this.$shadow)[0]
        )
      })
    )

    hotkeys(`${metaKey}+/,${metaKey}+.`, e =>
      this.$shadow.host.style.display =
        this.$shadow.host.style.display === 'none'
          ? 'block'
          : 'none')
  }

  cleanup() {
    Array.from(document.body.children)
      .filter(node => node.nodeName.includes('VISBUG'))
      .forEach(el => el.remove())

    this.teardown();

    document.querySelectorAll('[data-pseudo-select=true]')
      .forEach(el =>
        el.removeAttribute('data-pseudo-select'))
  }

  toolSelected(el) {
    if (typeof el === 'string')
      el = $(`[data-tool="${el}"]`, this.$shadow)[0]

    if (this.active_tool && this.active_tool.dataset.tool === el.dataset.tool) return

    if (this.active_tool) {
      this.active_tool.attr('data-active', null)
      this.deactivate_feature()
    }

    el.attr('data-active', true)
    this.active_tool = el
    this[el.dataset.tool]()
  }

  render() {
    return `
      <visbug-hotkeys></visbug-hotkeys>

        ${Object.entries(this.toolbar_model).reduce((list, [key, tool]) => `
          ${list}

            ${tool.icon}
            ${this.demoTip({key, ...tool})}

        `,'')}

          <input type="color" value="">
          ${Icons.color_text}

          <input type="color" value="">
          ${Icons.color_background}

          <input type="color" value="">
          ${Icons.color_border}

    `
  }

  demoTip({key, tool, label, description, instruction}) {
    return `

              ${label}
              ${key}

${description}

            ${instruction}

    `
  }

  move() {
    this.deactivate_feature = Moveable(this.selectorEngine)
  }

  margin() {
    this.deactivate_feature = Margin(this.selectorEngine)
  }

  padding() {
    this.deactivate_feature = Padding(this.selectorEngine)
  }

  font() {
    this.deactivate_feature = Font(this.selectorEngine)
  }

  text() {
    this.selectorEngine.onSelectedUpdate(EditText)
    this.deactivate_feature = () =>
      this.selectorEngine.removeSelectedCallback(EditText)
  }

  align() {
    this.deactivate_feature = Flex(this.selectorEngine)
  }

  search() {
    this.deactivate_feature = Search($('[data-tool="search"]', this.$shadow))
  }

  boxshadow() {
    this.deactivate_feature = BoxShadow(this.selectorEngine)
  }

  hueshift() {
    this.deactivate_feature = HueShift({
      Color:  this.colorPicker,
      Visbug: this.selectorEngine,
    })
  }

  inspector() {
    this.deactivate_feature = MetaTip(this.selectorEngine)
  }

  accessibility() {
    this.deactivate_feature = Accessibility(this.selectorEngine)
  }

  guides() {
    this.deactivate_feature = Guides(this.selectorEngine)
  }

  screenshot() {
    this.deactivate_feature = Screenshot()
  }

  position() {
    let feature = Position()
    this.selectorEngine.onSelectedUpdate(feature.onNodesSelected)
    this.deactivate_feature = () => {
      this.selectorEngine.removeSelectedCallback(feature.onNodesSelected)
      feature.disconnect()
    }
  }

  execCommand(command) {
    const query = `/${command}`

    if (PluginRegistry.has(query))
      return PluginRegistry.get(query)({
        selected: this.selectorEngine.selection(),
        query
      })

    return Promise.resolve(new Error("Query not found"))
  }

  get activeTool() {
    return this.active_tool.dataset.tool
  }

  set tutsBaseURL(url) {
    this._tutsBaseURL = url
    this.setup()
  }

  set colorMode(mode) {
    this._colormode = modemap[mode]
  }

  get colorMode() {
    return this._colormode
  }
}

customElements.define('vis-bug', VisBug)
<|endoftext|>


<commit_before>'use strict';

goog.provide('Blockly.Python.hedgehog');

goog.require('Blockly.Python');

// set indentaion to 4 spaces
Blockly.Python.INDENT = '    ';

Blockly.Python['hedgehog_scope'] = function(block) {
    var statements = Blockly.Python.statementToCode(block, 'IN');
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'with connect(emergency=15) as hedgehog:\n' + statements;
    return code;
};

Blockly.Python['hedgehog_turn'] = function(block) {
    var port1 = block.getFieldValue('MOTOR1');
    var port2 = block.getFieldValue('MOTOR2');
    var dir = parseInt(Blockly.Python.valueToCode(block, 'DIR', Blockly.Python.ORDER_NONE));
    var time = Blockly.Python.valueToCode(block, 'TIME', Blockly.Python.ORDER_ATOMIC);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'hedgehog.move(' + port1 + ', ' + dir + ')\n';
    code += 'hedgehog.move(' + port2 + ', ' + (-1 * dir) + ')\n';
    code += 'sleep(' + time + ')\n\n';

    return code;
};

Blockly.Python['hedgehog_move2'] = function(block) {
    var port1 = block.getFieldValue('MOTOR1');
    var port2 = block.getFieldValue('MOTOR2');
    var speed = Blockly.Python.valueToCode(block, 'SPEED', Blockly.Python.ORDER_NONE);
    var time = Blockly.Python.valueToCode(block, 'TIME', Blockly.Python.ORDER_ATOMIC);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'hedgehog.move(' + port1 + ', ' + speed + ')\n';
    var code = 'hedgehog.move(' + port2 + ', ' + speed + ')\n';
    code += 'sleep(' + time + ')\n\n';
    return code;
};

Blockly.Python['hedgehog_move'] = function(block) {
    var port = block.getFieldValue('PORT');
    var speed = Blockly.Python.valueToCode(block, 'SPEED', Blockly.Python.ORDER_NONE);
    var time = Blockly.Python.valueToCode(block, 'TIME', Blockly.Python.ORDER_ATOMIC);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'hedgehog.move(' + port + ', ' + speed + ')' + '\nsleep(' + time + ')\n\n';
    return code;
};

Blockly.Python['hedgehog_speed'] = function(block) {
    var speed = block.getFieldValue('SPEED');
    return [speed, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_dir'] = function(block) {
    var speed = block.getFieldValue('DIR');
    return [speed, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_servo'] = function(block) {
    var port = block.getFieldValue('PORT');
    var angle = Blockly.Python.valueToCode(block, 'ANGLE', Blockly.Python.ORDER_NONE);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'hedgehog.set_servo(' + port + ', True, ' + angle + '*22' + ')\n';
    code += 'sleep(0.1)\n\n';
    return code;
};

Blockly.Python['hedgehog_degrees'] = function(block) {
    var angle = block.getFieldValue('ANGLE');

    // imports
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    if(parseInt(angle) > 180) {
        return ["180", Blockly.Python.ORDER_NONE];
    }

    return [angle, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_read_analog'] = function(block) {
    var port = block.getFieldValue('PORT');

    var code = 'hedgehog.get_analog(' + port + ')';
    return [code, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_read_digital'] = function(block) {
    var port = block.getFieldValue('PORT');

    var code = 'hedgehog.get_digital(' + port + ')';
    return [code, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_sleep'] = function(block) {
    var time = Blockly.Python.valueToCode(block, 'TIME', Blockly.Python.ORDER_ATOMIC);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';

    var code = 'sleep(' + time + ')\n\n';
    return code;
};
<commit_msg>directly convert angle to 0-2048<commit_after>'use strict';

goog.provide('Blockly.Python.hedgehog');

goog.require('Blockly.Python');

// set indentaion to 4 spaces
Blockly.Python.INDENT = '    ';

Blockly.Python['hedgehog_scope'] = function(block) {
    var statements = Blockly.Python.statementToCode(block, 'IN');
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'with connect(emergency=15) as hedgehog:\n' + statements;
    return code;
};

Blockly.Python['hedgehog_turn'] = function(block) {
    var port1 = block.getFieldValue('MOTOR1');
    var port2 = block.getFieldValue('MOTOR2');
    var dir = parseInt(Blockly.Python.valueToCode(block, 'DIR', Blockly.Python.ORDER_NONE));
    var time = Blockly.Python.valueToCode(block, 'TIME', Blockly.Python.ORDER_ATOMIC);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'hedgehog.move(' + port1 + ', ' + dir + ')\n';
    code += 'hedgehog.move(' + port2 + ', ' + (-1 * dir) + ')\n';
    code += 'sleep(' + time + ')\n\n';

    return code;
};

Blockly.Python['hedgehog_move2'] = function(block) {
    var port1 = block.getFieldValue('MOTOR1');
    var port2 = block.getFieldValue('MOTOR2');
    var speed = Blockly.Python.valueToCode(block, 'SPEED', Blockly.Python.ORDER_NONE);
    var time = Blockly.Python.valueToCode(block, 'TIME', Blockly.Python.ORDER_ATOMIC);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'hedgehog.move(' + port1 + ', ' + speed + ')\n';
    var code = 'hedgehog.move(' + port2 + ', ' + speed + ')\n';
    code += 'sleep(' + time + ')\n\n';
    return code;
};

Blockly.Python['hedgehog_move'] = function(block) {
    var port = block.getFieldValue('PORT');
    var speed = Blockly.Python.valueToCode(block, 'SPEED', Blockly.Python.ORDER_NONE);
    var time = Blockly.Python.valueToCode(block, 'TIME', Blockly.Python.ORDER_ATOMIC);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'hedgehog.move(' + port + ', ' + speed + ')' + '\nsleep(' + time + ')\n\n';
    return code;
};

Blockly.Python['hedgehog_speed'] = function(block) {
    var speed = block.getFieldValue('SPEED');
    return [speed, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_dir'] = function(block) {
    var speed = block.getFieldValue('DIR');
    return [speed, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_servo'] = function(block) {
    var port = block.getFieldValue('PORT');
    var angle = Blockly.Python.valueToCode(block, 'ANGLE', Blockly.Python.ORDER_NONE);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    var code = 'hedgehog.set_servo(' + port + ', True, ' + Math.floor(parseInt(angle)*11.37) + ')\n';
    code += 'sleep(0.1)\n\n';
    return code;
};

Blockly.Python['hedgehog_degrees'] = function(block) {
    var angle = block.getFieldValue('ANGLE');

    // imports
    Blockly.Python.definitions_['import_hedgehog'] = 'from hedgehog.client import connect';

    if(parseInt(angle) > 180) {
        return ["180", Blockly.Python.ORDER_NONE];
    }

    return [angle, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_read_analog'] = function(block) {
    var port = block.getFieldValue('PORT');

    var code = 'hedgehog.get_analog(' + port + ')';
    return [code, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_read_digital'] = function(block) {
    var port = block.getFieldValue('PORT');

    var code = 'hedgehog.get_digital(' + port + ')';
    return [code, Blockly.Python.ORDER_NONE];
};

Blockly.Python['hedgehog_sleep'] = function(block) {
    var time = Blockly.Python.valueToCode(block, 'TIME', Blockly.Python.ORDER_ATOMIC);

    // imports
    Blockly.Python.definitions_['import_sleep'] = 'from time import sleep';

    var code = 'sleep(' + time + ')\n\n';
    return code;
};
<|endoftext|>


<commit_before>"use strict";

var Promise = require('bluebird')
  , models = require('../../../models')
  , exceptions = require('../../../support/exceptions')
  , PostSerializer = models.PostSerializer
  , FeedFactory = models.FeedFactory
  , pubSub = models.PubSub
  , ForbiddenException = exceptions.ForbiddenException
  , _ = require('lodash')

exports.addController = function(app) {
  /**
   * @constructor
   */
  var PostsController = function() {
  }

  PostsController.create = async function(req, res) {
    if (!req.user) {
      res.status(401).jsonp({ err: 'Not found' })
      return
    }

    var feeds = []
    req.body.meta = req.body.meta || {}

    if (_.isArray(req.body.meta.feeds)) {
      feeds = req.body.meta.feeds
    } else if (req.body.meta.feeds) {
      feeds = [req.body.meta.feeds]
    } else {
      res.status(401).jsonp({ err: 'Cannot publish post to /dev/null' })
      return
    }

    try {
      let promises = feeds.map(async (username) => {
        let feed = await FeedFactory.findByUsername(username)
        await feed.validateCanPost(req.user)

        // we are going to publish this message to posts feed if
        // it's my home feed or group's feed, otherwise this is a
        // private message that goes to its own feed(s)
        if (
          (feed.isUser() && feed.id == req.user.id) ||
          !feed.isUser()
        ) {
          return feed.getPostsTimelineId()
        } else {
          // private post goes to sendee and sender
          return await Promise.all([
            feed.getDirectsTimelineId(),
            req.user.getDirectsTimelineId()
          ])
        }
      })
      let timelineIds = _.flatten(await Promise.all(promises))

      let newPost = await req.user.newPost({
        body: req.body.post.body,
        attachments: req.body.post.attachments,
        timelineIds: timelineIds
      })

      await newPost.create()

      let json = await new PostSerializer(newPost).promiseToJSON()
      res.jsonp(json)
    } catch (e) {
      exceptions.reportError(res)(e)
    }
  }

  PostsController.update = function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    models.Post.findById(req.params.postId)
      .then(function(post) {
        if (post.userId != req.user.id) {
          return Promise.reject(new ForbiddenException(
              "You can't update another user's post"))
        }
        return post.update({
          body: req.body.post.body,
          attachments: req.body.post.attachments
        })
      })
      .then(function(post) {
        new PostSerializer(post).toJSON(function(err, json) {
          res.jsonp(json)
        })
      })
      .catch(exceptions.reportError(res))
  }

  PostsController.show = async function(req, res) {
    try {
      var userId = req.user ? req.user.id : null
      var post = await models.Post.getById(req.params.postId, {
        maxComments: req.query.maxComments,
        maxLikes: req.query.maxLikes,
        currentUser: userId
      })

      var valid = await post.validateCanShow(userId)

      // this is a private post
      if (!valid)
        throw new ForbiddenException("Not found")

      var author = await models.User.findById(post.userId)
      var banIds = await author.getBanIds()
      if (banIds.indexOf(post.currentUser) >= 0)
        throw new ForbiddenException("This user has prevented you from seeing their posts")

      var you = await models.User.findById(post.currentUser)
      if (you) {
        var yourBanIds = await you.getBanIds()
        if (yourBanIds.indexOf(author.id) >= 0)
          throw new ForbiddenException("You have blocked this user and do not want to see their posts")
      }

      var json = new PostSerializer(post).promiseToJSON()

      res.jsonp(await json)
    } catch(e) {
      exceptions.reportError(res)(e)
    }
  }

  PostsController.like = async function(req, res) {
    if (!req.user) {
      res.status(401).jsonp({ err: 'Not found' })
      return
    }

    try {
      let post = await models.Post.getById(req.params.postId)
      let affectedTimelines = await post.addLike(req.user)

      let stats = await models.Stats.findById(req.user.id)
      await stats.addLike()

      res.status(200).send({})

      await pubSub.newLike(post, req.user.id, affectedTimelines)
    } catch(e) {
      exceptions.reportError(res)(e)
    }
  }

  PostsController.unlike = async function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    try {
      let post = await models.Post.getById(req.params.postId)
      await post.removeLike(req.user.id)
      res.status(200).send({})
    } catch(e) {
      exceptions.reportError(res)(e)
    }
  }

  PostsController.destroy = function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    models.Post.getById(req.params.postId)
      .then(function(post) {
          if (post.userId != req.user.id) {
            return Promise.reject(new ForbiddenException(
                "You can't delete another user's post"))
          }
          return post.destroy()
        })
      .then(function(status) { res.jsonp({}) })
      .catch(exceptions.reportError(res))
  }

  PostsController.hide = function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    models.Post.getById(req.params.postId)
      .then(function(post) { return post.hide(req.user.id) })
      .then(function() { res.jsonp({} )})
      .catch(exceptions.reportError(res))
  }

  PostsController.unhide = function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    models.Post.getById(req.params.postId)
      .then(function(post) { return post.unhide(req.user.id) })
      .then(function() { res.jsonp({} )})
      .catch(exceptions.reportError(res))
  }

  return PostsController
}
<commit_msg>do not try to query redis for data of anonymous<commit_after>"use strict";

var Promise = require('bluebird')
  , models = require('../../../models')
  , exceptions = require('../../../support/exceptions')
  , PostSerializer = models.PostSerializer
  , FeedFactory = models.FeedFactory
  , pubSub = models.PubSub
  , ForbiddenException = exceptions.ForbiddenException
  , _ = require('lodash')

exports.addController = function(app) {
  /**
   * @constructor
   */
  var PostsController = function() {
  }

  PostsController.create = async function(req, res) {
    if (!req.user) {
      res.status(401).jsonp({ err: 'Not found' })
      return
    }

    var feeds = []
    req.body.meta = req.body.meta || {}

    if (_.isArray(req.body.meta.feeds)) {
      feeds = req.body.meta.feeds
    } else if (req.body.meta.feeds) {
      feeds = [req.body.meta.feeds]
    } else {
      res.status(401).jsonp({ err: 'Cannot publish post to /dev/null' })
      return
    }

    try {
      let promises = feeds.map(async (username) => {
        let feed = await FeedFactory.findByUsername(username)
        await feed.validateCanPost(req.user)

        // we are going to publish this message to posts feed if
        // it's my home feed or group's feed, otherwise this is a
        // private message that goes to its own feed(s)
        if (
          (feed.isUser() && feed.id == req.user.id) ||
          !feed.isUser()
        ) {
          return feed.getPostsTimelineId()
        } else {
          // private post goes to sendee and sender
          return await Promise.all([
            feed.getDirectsTimelineId(),
            req.user.getDirectsTimelineId()
          ])
        }
      })
      let timelineIds = _.flatten(await Promise.all(promises))

      let newPost = await req.user.newPost({
        body: req.body.post.body,
        attachments: req.body.post.attachments,
        timelineIds: timelineIds
      })

      await newPost.create()

      let json = await new PostSerializer(newPost).promiseToJSON()
      res.jsonp(json)
    } catch (e) {
      exceptions.reportError(res)(e)
    }
  }

  PostsController.update = function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    models.Post.findById(req.params.postId)
      .then(function(post) {
        if (post.userId != req.user.id) {
          return Promise.reject(new ForbiddenException(
              "You can't update another user's post"))
        }
        return post.update({
          body: req.body.post.body,
          attachments: req.body.post.attachments
        })
      })
      .then(function(post) {
        new PostSerializer(post).toJSON(function(err, json) {
          res.jsonp(json)
        })
      })
      .catch(exceptions.reportError(res))
  }

  PostsController.show = async function(req, res) {
    try {
      var userId = req.user ? req.user.id : null
      var post = await models.Post.getById(req.params.postId, {
        maxComments: req.query.maxComments,
        maxLikes: req.query.maxLikes,
        currentUser: userId
      })

      var valid = await post.validateCanShow(userId)

      // this is a private post
      if (!valid)
        throw new ForbiddenException("Not found")

      if (post.currentUser) {
        let author = await models.User.findById(post.userId)
        let banIds = await author.getBanIds()

        if (banIds.indexOf(post.currentUser) >= 0)
          throw new ForbiddenException("This user has prevented you from seeing their posts")

        let you = await models.User.findById(post.currentUser)

        if (you) {
          let yourBanIds = await you.getBanIds()

          if (yourBanIds.indexOf(author.id) >= 0)
            throw new ForbiddenException("You have blocked this user and do not want to see their posts")
        }
      }

      var json = new PostSerializer(post).promiseToJSON()

      res.jsonp(await json)
    } catch(e) {
      exceptions.reportError(res)(e)
    }
  }

  PostsController.like = async function(req, res) {
    if (!req.user) {
      res.status(401).jsonp({ err: 'Not found' })
      return
    }

    try {
      let post = await models.Post.getById(req.params.postId)
      let affectedTimelines = await post.addLike(req.user)

      let stats = await models.Stats.findById(req.user.id)
      await stats.addLike()

      res.status(200).send({})

      await pubSub.newLike(post, req.user.id, affectedTimelines)
    } catch(e) {
      exceptions.reportError(res)(e)
    }
  }

  PostsController.unlike = async function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    try {
      let post = await models.Post.getById(req.params.postId)
      await post.removeLike(req.user.id)
      res.status(200).send({})
    } catch(e) {
      exceptions.reportError(res)(e)
    }
  }

  PostsController.destroy = function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    models.Post.getById(req.params.postId)
      .then(function(post) {
          if (post.userId != req.user.id) {
            return Promise.reject(new ForbiddenException(
                "You can't delete another user's post"))
          }
          return post.destroy()
        })
      .then(function(status) { res.jsonp({}) })
      .catch(exceptions.reportError(res))
  }

  PostsController.hide = function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    models.Post.getById(req.params.postId)
      .then(function(post) { return post.hide(req.user.id) })
      .then(function() { res.jsonp({} )})
      .catch(exceptions.reportError(res))
  }

  PostsController.unhide = function(req, res) {
    if (!req.user)
      return res.status(401).jsonp({ err: 'Not found' })

    models.Post.getById(req.params.postId)
      .then(function(post) { return post.unhide(req.user.id) })
      .then(function() { res.jsonp({} )})
      .catch(exceptions.reportError(res))
  }

  return PostsController
}
<|endoftext|>


<commit_before>// Convert usergroups
//

'use strict';

const _  = require('lodash');
const co = require('co');

/* eslint-disable no-bitwise */
module.exports = co.wrap(function* (N) {
  let conn = yield N.vbconvert.getConnection();

  let rows = yield conn.query(`
    SELECT usergroupid,title
    FROM usergroup
  `);

  let configs = N.config.vbconvert.usergroups;

  let store = N.settings.getStore('usergroup');

  if (!store) throw 'Settings store `usergroup` is not registered.';

  for (let row of rows) {
    row.config = configs[row.usergroupid];
    row.settings = (row.config || {}).settings || {};
  }

  yield rows.map(co.wrap(function* (row) {
    let usergroup, config = row.config;

    // ignore some usergroups
    if (!config) return;

    usergroup = yield N.models.users.UserGroup.findOne({ short_name: config.short_name }).lean(false);

    if (!usergroup) {
      usergroup = new N.models.users.UserGroup({ short_name: config.short_name });
    }

    try {
      yield new N.models.vbconvert.UserGroupMapping({
        mysql: row.usergroupid,
        mongo: usergroup._id
      }).save();
    } catch (err) {
      // ignore duplicate key errors
      if (err.code !== 11000) throw err;

      return;
    }

    yield usergroup.save();
  }));

  // update parent_group
  yield rows.map(co.wrap(function* (row) {
    let config = row.config;

    if (!config) return;
    if (!config.parent) return;

    let usergroup = yield N.models.users.UserGroup.findOne({ short_name: config.short_name }).lean(false);
    let parent    = yield N.models.users.UserGroup.findOne({ short_name: config.parent }).lean(true);

    usergroup.parent_group = parent._id;
    yield usergroup.save();
  }));

  yield store.updateInherited();

  // update permissions
  yield rows.map(co.wrap(function* (row) {
    let config = row.config;

    if (!config) return;

    let usergroup = yield N.models.users.UserGroup.findOne({ short_name: config.short_name }).lean(true);
    let should_be = row.settings;

    if (!Object.keys(should_be).length) return;

    let settings = yield store.get(Object.keys(should_be), { usergroup_ids: [ usergroup._id ] });

    if (config.parent) {
      let parent = _.find(rows, r => r.config && r.config.short_name === config.parent);

      for (let key of Object.keys(parent.settings)) {
        settings[key] = parent.settings[key];
      }
    }

    let update = {};

    Object.keys(should_be).forEach(key => {
      if ((!settings[key].force !== !should_be[key].force) ||
         (!settings[key].value !== !should_be[key].value)) {

        update[key] = should_be[key];
      }
    });

    yield store.set(update, { usergroup_id: usergroup._id });
  }));

  yield store.updateInherited();

  conn.release();
  N.logger.info('UserGroup import finished');
});
<commit_msg>Change inherited settings in usergroup store<commit_after>// Convert usergroups
//

'use strict';

const _  = require('lodash');
const co = require('co');

/* eslint-disable no-bitwise */
module.exports = co.wrap(function* (N) {
  let conn = yield N.vbconvert.getConnection();

  let rows = yield conn.query(`
    SELECT usergroupid,title
    FROM usergroup
  `);

  let configs = N.config.vbconvert.usergroups;

  let store = N.settings.getStore('usergroup');

  if (!store) throw 'Settings store `usergroup` is not registered.';

  for (let row of rows) {
    row.config = configs[row.usergroupid];
    row.settings = (row.config || {}).settings || {};
  }

  yield rows.map(co.wrap(function* (row) {
    let usergroup, config = row.config;

    // ignore some usergroups
    if (!config) return;

    usergroup = yield N.models.users.UserGroup.findOne({ short_name: config.short_name }).lean(false);

    if (!usergroup) {
      usergroup = new N.models.users.UserGroup({ short_name: config.short_name });
    }

    try {
      yield new N.models.vbconvert.UserGroupMapping({
        mysql: row.usergroupid,
        mongo: usergroup._id
      }).save();
    } catch (err) {
      // ignore duplicate key errors
      if (err.code !== 11000) throw err;

      return;
    }

    yield usergroup.save();
  }));

  // update parent_group
  yield rows.map(co.wrap(function* (row) {
    let config = row.config;

    if (!config) return;
    if (!config.parent) return;

    let usergroup = yield N.models.users.UserGroup.findOne({ short_name: config.short_name }).lean(false);
    let parent    = yield N.models.users.UserGroup.findOne({ short_name: config.parent }).lean(true);

    usergroup.parent_group = parent._id;
    yield usergroup.save();
  }));

  // update permissions
  yield rows.map(co.wrap(function* (row) {
    let config = row.config;

    if (!config) return;

    let usergroup = yield N.models.users.UserGroup.findOne({ short_name: config.short_name }).lean(true);
    let should_be = row.settings;

    if (!Object.keys(should_be).length) return;

    let settings = yield store.get(Object.keys(should_be), { usergroup_ids: [ usergroup._id ] });

    if (config.parent) {
      let parent = _.find(rows, r => r.config && r.config.short_name === config.parent);

      for (let key of Object.keys(parent.settings)) {
        settings[key] = parent.settings[key];
      }
    }

    let update = {};

    Object.keys(should_be).forEach(key => {
      if ((!settings[key].force !== !should_be[key].force) ||
         (!settings[key].value !== !should_be[key].value)) {

        update[key] = should_be[key];
      }
    });

    yield store.set(update, { usergroup_id: usergroup._id });
  }));

  conn.release();
  N.logger.info('UserGroup import finished');
});
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.charSet2 = exports.charSet4 = exports.charSet8 = exports.charSet16 = exports.charSet32 = exports.charSet64 = undefined;

var _log = require('babel-runtime/core-js/math/log2');

var _log2 = _interopRequireDefault(_log);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _lcm = require('./lcm');

var _lcm2 = _interopRequireDefault(_lcm);

var _weakMap = require('weak-map');

var _weakMap2 = _interopRequireDefault(_weakMap);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var propMap = new _weakMap2.default();
var bitsPerByte = 8;

var CharSet = function () {
  function CharSet(chars) {
    (0, _classCallCheck3.default)(this, CharSet);

    if (!(typeof chars === 'string' || chars instanceof String)) {
      throw new Error('Invalid chars: Must be string');
    }
    var length = chars.length;
    if (![2, 4, 8, 16, 32, 64].includes(length)) {
      throw new Error('Invalid char count: must be one of 2,4,8,16,32,64');
    }
    var bitsPerChar = Math.floor((0, _log2.default)(length));
    // Ensure no repeated characters
    for (var i = 0; i < length; i++) {
      var c = chars.charAt(i);
      for (var j = i + 1; j < length; j++) {
        if (c === chars.charAt(j)) {
          throw new Error('Characters not unique');
        }
      }
    }
    var privProps = {
      chars: chars,
      bitsPerChar: bitsPerChar,
      length: length,
      ndxFn: _ndxFn(bitsPerChar),
      charsPerChunk: (0, _lcm2.default)(bitsPerChar, bitsPerByte) / bitsPerChar
    };
    propMap.set(this, privProps);
  }

  (0, _createClass3.default)(CharSet, [{
    key: 'getChars',
    value: function getChars() {
      return propMap.get(this).chars;
    }
  }, {
    key: 'getBitsPerChar',
    value: function getBitsPerChar() {
      return propMap.get(this).bitsPerChar;
    }
  }, {
    key: 'getNdxFn',
    value: function getNdxFn() {
      return propMap.get(this).ndxFn;
    }
  }, {
    key: 'getCharsPerChunk',
    value: function getCharsPerChunk() {
      return propMap.get(this).charsPerChunk;
    }
  }, {
    key: 'length',
    value: function length() {
      return propMap.get(this).length;
    }
  }, {
    key: 'getNdxFn',
    value: function getNdxFn() {
      return propMap.get(this).ndxFn;
    }

    // Aliases

  }, {
    key: 'chars',
    value: function chars() {
      return this.getChars();
    }
  }, {
    key: 'ndxFn',
    value: function ndxFn() {
      return this.getNdxFn();
    }
  }]);
  return CharSet;
}();

exports.default = CharSet;

var _ndxFn = function _ndxFn(bitsPerChar) {
  // If bitsPerBytes is a multiple of bitsPerChar, we can slice off an integer number
  // of chars per byte.
  if ((0, _lcm2.default)(bitsPerChar, bitsPerByte) === bitsPerByte) {
    return function (chunk, slice, bytes) {
      var lShift = bitsPerChar;
      var rShift = bitsPerByte - bitsPerChar;
      return (bytes[chunk] << lShift * slice & 0xff) >> rShift;
    };
  }
  // Otherwise, while slicing off bits per char, we will possibly straddle a couple
  // of bytes, so a bit more work is involved
  else {
      return function (chunk, slice, bytes) {
        var slicesPerChunk = (0, _lcm2.default)(bitsPerChar, bitsPerByte) / bitsPerByte;
        var bNum = chunk * slicesPerChunk;

        var rShift = bitsPerByte - bitsPerChar;
        var lOffset = Math.floor(slice * bitsPerChar / bitsPerByte);
        var lShift = slice * bitsPerChar % bitsPerByte;

        var ndx = (bytes[bNum + lOffset] << lShift & 0xff) >> rShift;

        var rOffset = Math.ceil(slice * bitsPerChar / bitsPerByte);
        var rShiftIt = ((rOffset + 1) * bitsPerByte - (slice + 1) * bitsPerChar) % bitsPerByte;
        if (rShift < rShiftIt) {
          ndx += bytes[bNum + rOffset] >> rShiftIt;
        }
        return ndx;
      };
    }
};

var charSet64 = exports.charSet64 = new CharSet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_');
var charSet32 = exports.charSet32 = new CharSet('2346789bdfghjmnpqrtBDFGHJLMNPQRT');
var charSet16 = exports.charSet16 = new CharSet('0123456789abcdef');
var charSet8 = exports.charSet8 = new CharSet('01234567');
var charSet4 = exports.charSet4 = new CharSet('ATCG');
var charSet2 = exports.charSet2 = new CharSet('01');<commit_msg>Upcase const<commit_after>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.charSet2 = exports.charSet4 = exports.charSet8 = exports.charSet16 = exports.charSet32 = exports.charSet64 = undefined;

var _log = require('babel-runtime/core-js/math/log2');

var _log2 = _interopRequireDefault(_log);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _lcm = require('./lcm');

var _lcm2 = _interopRequireDefault(_lcm);

var _weakMap = require('weak-map');

var _weakMap2 = _interopRequireDefault(_weakMap);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var propMap = new _weakMap2.default();

var BITS_PER_BYTE = 8;

var CharSet = function () {
  function CharSet(chars) {
    (0, _classCallCheck3.default)(this, CharSet);

    if (!(typeof chars === 'string' || chars instanceof String)) {
      throw new Error('Invalid chars: Must be string');
    }
    var length = chars.length;
    if (![2, 4, 8, 16, 32, 64].includes(length)) {
      throw new Error('Invalid char count: must be one of 2,4,8,16,32,64');
    }
    var bitsPerChar = Math.floor((0, _log2.default)(length));
    // Ensure no repeated characters
    for (var i = 0; i < length; i++) {
      var c = chars.charAt(i);
      for (var j = i + 1; j < length; j++) {
        if (c === chars.charAt(j)) {
          throw new Error('Characters not unique');
        }
      }
    }
    var privProps = {
      chars: chars,
      bitsPerChar: bitsPerChar,
      length: length,
      ndxFn: _ndxFn(bitsPerChar),
      charsPerChunk: (0, _lcm2.default)(bitsPerChar, BITS_PER_BYTE) / bitsPerChar
    };
    propMap.set(this, privProps);
  }

  (0, _createClass3.default)(CharSet, [{
    key: 'getChars',
    value: function getChars() {
      return propMap.get(this).chars;
    }
  }, {
    key: 'getBitsPerChar',
    value: function getBitsPerChar() {
      return propMap.get(this).bitsPerChar;
    }
  }, {
    key: 'getNdxFn',
    value: function getNdxFn() {
      return propMap.get(this).ndxFn;
    }
  }, {
    key: 'getCharsPerChunk',
    value: function getCharsPerChunk() {
      return propMap.get(this).charsPerChunk;
    }
  }, {
    key: 'length',
    value: function length() {
      return propMap.get(this).length;
    }
  }, {
    key: 'getNdxFn',
    value: function getNdxFn() {
      return propMap.get(this).ndxFn;
    }
  }, {
    key: 'bytesNeeded',
    value: function bytesNeeded(entropyBits) {
      var count = Math.ceil(entropyBits / this.bitsPerChar());
      return Math.ceil(count * this.bitsPerChar() / BITS_PER_BYTE);
    }

    // Aliases

  }, {
    key: 'chars',
    value: function chars() {
      return this.getChars();
    }
  }, {
    key: 'ndxFn',
    value: function ndxFn() {
      return this.getNdxFn();
    }
  }, {
    key: 'bitsPerChar',
    value: function bitsPerChar() {
      return this.getBitsPerChar();
    }
  }]);
  return CharSet;
}();

exports.default = CharSet;

var _ndxFn = function _ndxFn(bitsPerChar) {
  // If BITS_PER_BYTEs is a multiple of bitsPerChar, we can slice off an integer number
  // of chars per byte.
  if ((0, _lcm2.default)(bitsPerChar, BITS_PER_BYTE) === BITS_PER_BYTE) {
    return function (chunk, slice, bytes) {
      var lShift = bitsPerChar;
      var rShift = BITS_PER_BYTE - bitsPerChar;
      return (bytes[chunk] << lShift * slice & 0xff) >> rShift;
    };
  }
  // Otherwise, while slicing off bits per char, we will possibly straddle a couple
  // of bytes, so a bit more work is involved
  else {
      var slicesPerChunk = (0, _lcm2.default)(bitsPerChar, BITS_PER_BYTE) / BITS_PER_BYTE;
      return function (chunk, slice, bytes) {
        var bNum = chunk * slicesPerChunk;

        var offset = slice * bitsPerChar / BITS_PER_BYTE;
        var lOffset = Math.floor(offset);
        var rOffset = Math.ceil(offset);

        var rShift = BITS_PER_BYTE - bitsPerChar;
        var lShift = slice * bitsPerChar % BITS_PER_BYTE;

        var ndx = (bytes[bNum + lOffset] << lShift & 0xff) >> rShift;

        var rShiftIt = ((rOffset + 1) * BITS_PER_BYTE - (slice + 1) * bitsPerChar) % BITS_PER_BYTE;
        if (rShift < rShiftIt) {
          ndx += bytes[bNum + rOffset] >> rShiftIt;
        }
        return ndx;
      };
    }
};

var charSet64 = exports.charSet64 = new CharSet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_');
var charSet32 = exports.charSet32 = new CharSet('2346789bdfghjmnpqrtBDFGHJLMNPQRT');
var charSet16 = exports.charSet16 = new CharSet('0123456789abcdef');
var charSet8 = exports.charSet8 = new CharSet('01234567');
var charSet4 = exports.charSet4 = new CharSet('ATCG');
var charSet2 = exports.charSet2 = new CharSet('01');<|endoftext|>


<commit_before>'use strict';
angular.module('ngTap', []).directive('ngTap', function() {
    return function(scope, element, attrs) {
        element.bind('tap', function() {
            scope.$apply(attrs.ngTap, element);
        });
    };
});
<commit_msg>Removing `'use strict';`<commit_after>angular.module('ngTap', []).directive('ngTap', function() {
    return function(scope, element, attrs) {
        element.bind('tap', function() {
            scope.$apply(attrs.ngTap, element);
        });
    };
});
<|endoftext|>


<commit_before>// TODO: Fill in some useful template language here<commit_msg>chore: Update container template<commit_after>import React, { Component } from 'react';
import { connect} from 'react-redux';

class RoomsList extends Component {
  render() {

  }
}

function mapStateToProps(state) {
  return {
    rooms: state.rooms
  };
}

export default connect(mapStateToProps)(RoomsList);<|endoftext|>