<commit_before>/* In this app $rootScope is mostly used for
 * changing the route and managing visibly of navigation bar.
 */
Appbase.credentials("aphrodite", "4d8d0072580912343cd74a09015cd217");
angular.module('twitter',['ngRoute','ngAppbase'])
  .run(function($rootScope,userSession,$location) {
    $rootScope.exit = function() {
      userSession.exit()
      $location.path('/global')
    }
    $rootScope.gotoProfile = function(userId){
      $location.path('/profile/'+userId)
    }
    $rootScope.search = function(text){
      $location.path('/search/'+text)
    }
    $rootScope.goHome = function(feed){
      $location.path('/home/'+feed)
    }
    $rootScope.hideNav = function (){
      $rootScope.$broadcast('hideNav',[1])
    }
    $rootScope.showNav = function (){
      $rootScope.$broadcast('showNav')
    }
    $rootScope.load = function() {
      $location.path('/loading')
    }
  })
  // Route management
  .config(function($routeProvider){
    $routeProvider
      .when('/',
      {
        controller:'global',
        templateUrl:'views/global.html'
      }
    ).when('/loading',
      {
        controller:'loading',
        templateUrl:'views/loading.html'
      }
    ).when('/search/:text',
      {
        controller:'search',
        templateUrl:'views/search.html'
      }
    ).when('/profile/:userId',
      {
        controller:'profile',
        templateUrl:'views/profile.html'
      }
    ).when('/home/:feed',
      {
        controller:'home',
        templateUrl:'views/home.html'
      }
    ).otherwise({redirectTo:'/'})
  })
  /* Controller: global
   * Shows all tweets when no one is logged in
   */
  .controller('global', function ($scope, userSession, $location,$rootScope,$appbaseRef) {
    // Navigation bar shouldn't be visible if no one is logged in
    $rootScope.hideNav()

    // Called when the user enter a name, or the user is already logged in
    $scope.login = function() {
      userSession.setUser($scope.userId.replace(/ /g, "_"))
      $location.path('/loading')
    }
    // Check if a user is already logged in the session
    if( $scope.userId = userSession.getUser()){
      $scope.login()
    }
    //Show all tweets
    $appbaseRef('global/tweets').$bindEdges($scope,'tweets')
  })
  /* Controller: search
   * Search's for tweets in Appbase and shows results
   */
  .controller('search', function ($scope, $rootScope, $routeParams) {
    // Getting the 'query text' from route parameters
    $scope.currentQuery = $routeParams.text
    // Searching in the namespace: __tweet__ for vertices, which contain 'query text' in the property: __msg__
    Appbase.search('tweet',{text: $routeParams.text, properties:['msg']},function(error, array) {
      $scope.tweets = array
      $scope.$apply()
    })
  })
  /* Controller: Loading
   * It inits the __data__ factory, which is used everywhere in the app to fetch and set data from/to Appbase.
   * After the _init_ completes, it takes the user to _home_ screen, showing personal tweets of the user.
   */
  .controller('loading', function ($rootScope,$scope, userSession, data) {
    if(!userSession.getUser()){
      $rootScope.exit()
      return
    }
    data.init(function() {
      $scope.$apply(function() {
        $rootScope.goHome('personal')
      })
    })
  })
  /* Controller: navbar
   * Handles button clicks and visibility of buttons
   */
  .controller('navbar',function($scope,userSession,$location,$rootScope,$routeParams){
    $scope.bahar = true
    // Called when user enters a text in the search box and presses Enter key
    $scope.search = function() {
      $rootScope.search($scope.searchText)
      $scope.searchText = ''
    }
    $scope.$on('showNav',function() {
      $scope.bahar = false
    })
    $scope.$on('hideNav',function() {
      $scope.bahar = true
    })
    $scope.exit= function() {
      $rootScope.exit()
    }
    $scope.gotoProfile= function(userId){
      if(userId === undefined)
        var userId = userSession.getUser()
      $rootScope.gotoProfile(userId)
    }
    $scope.goHome = function(feed){
      $rootScope.goHome(feed)
    }
  })
  /* Controller: home
   * This is what the user sees first when logged in. It shows the personal and global tweet feeds
   * The personal tweet feed: shows tweets from people he follows
   * The global feed: tweets by everyone
   */
  .controller('home',function($scope,userSession,$location,$rootScope,$appbaseRef,$routeParams,data){
    // Check if the session is properly initiated,
    // i.e. the 'data' factory set the flag 'initComplete' in userSession
    if(!userSession.initComplete) {
      if(!userSession.getUser())
        $rootScope.exit()
      else
        $rootScope.load()
      return
    }
    $rootScope.showNav()
    //Get __feed__ from route parameters
    var feed = $routeParams.feed === undefined? 'global': $routeParams.feed
    $scope.tweets = []
    $scope.people = []
    $scope.userName = userSession.getUser()
    $scope.gotoProfile = $rootScope.gotoProfile
    //Show _People on Twitter_, user's _Followers_ and _Followings_
    $appbaseRef(data.refs.allUsers).$bindEdges($scope,'people')
    $appbaseRef(data.refs.usersFollowers).$bindEdges($scope,'followers')
    $appbaseRef(data.refs.usersFollowing).$bindEdges($scope,'following')

    //Called when user posts a new tweet
    $scope.addTweet = function() {
      data.addTweet($scope.msg)
      $scope.msg = ''
    }
    if(feed === 'global') {
      // Show all tweets
      $appbaseRef(data.refs.globalTweets).$bindEdges($scope,'tweets')
    } else {
      /* Fetch tweets of the people followed by the user. Every following's tweets are pushed into `arraysOfTweets` as an array,
       * and in the end, these arrays are merged into personalTweets by calling `personalTweets.concat.apply(personalTweets, arraysOfTweets)`
       * in _home.html_
       */
      $scope.personalTweets = []
      $scope.arraysOfTweets = []
      $scope.arraysOfTweets.push($appbaseRef('user/'+userSession.getUser()+'/tweets').$bindEdges($scope))
      var usrRef = Appbase.ref('user/'+userSession.getUser()+'/following')
      usrRef.on('edge_added',function(error, followUserRef) {
        if(error) throw error
        $scope.arraysOfTweets.push($appbaseRef(followUserRef).$outVertex('tweets').$bindEdges($scope))
      })
      $scope.$on('$destroy',function() {
        //Stop listening to user's followings when the view is destroyed.
        usrRef.off()
      })
    }
  })
  /* Controller: profile
   * Where a user's followings, followers and tweets are shown.
   * A user can also see other's profiles and choose to follow/unfollow the person from his/her profile.
   */
  .controller('profile',function($scope,userSession,$location,$rootScope,$routeParams,$appbaseRef,data){
    if(!userSession.initComplete) {
      if(!userSession.getUser())
        $rootScope.exit()
      else
        $rootScope.load()
      return
    }
    $rootScope.showNav()

    //Get the userId from route params
    var userId = $routeParams.userId
    $scope.userId = $routeParams.userId
    //Check whether this profile is of the logged in user
    $scope.isMe = userSession.getUser() === userId
    $scope.userName = $routeParams.userId
    $scope.isReady = false

    //Check whether this user is being followed by the logged in user
    // This has to be an async function, as it interacts with the Appbase server
    !$scope.isMe && data.isUserBeingFollowed(userId,function(boolean){
      //If true, _unfollow_ button will appear, otherwise _follow_ one
      $scope.isBeingFollowed = boolean
      //Show _follow_ or _unfollow_ buttons only when the data is arrived
      $scope.isReady = true
    })
    $scope.gotoProfile = $rootScope.gotoProfile
    $scope.follow = function(userId){
      $scope.isBeingFollowed = true
      data.follow(userId)
    }
    $scope.unFollow = function(userId){
      $scope.isBeingFollowed = false
      data.unFollow(userId)
    }
    $scope.addTweet = function() {
      data.addTweet($scope.msg)
      $scope.msg = ''
    }
    //Fetch user's followers, followings and tweets
    $appbaseRef('user/'+userId+'/followers').$bindEdges($scope,'followers')
    $appbaseRef('user/'+userId+'/following').$bindEdges($scope,'following')
    $appbaseRef('user/'+userId+'/tweets').$bindEdges($scope,'tweets')
  })
  /*
   * Factory: data
   * Stores frequently useful Appbase references and interacts with Appbase for data needs
   */
  .factory('data',function(userSession) {
    // Appbase references
    var refs = {
      globalTweets: Appbase.ref('global/tweets'),
      allUsers: Appbase.ref('global/users')
    }
    // Factory to be exported
    var data = {
      refs:refs
    }
    // Called when the user just logs in.
    // It sets required references and creates basic data for a new user
    data.init = function(ready) {
      var userId = userSession.getUser()
      refs.user = Appbase.create('user',userSession.getUser())
      refs.usersTweets = refs.user.outVertex('tweets')
      refs.usersFollowers = refs.user.outVertex('followers')
      refs.usersFollowing = refs.user.outVertex('following')
      refs.user.on('properties',function(error, ref, snap) {
        refs.user.off()
        if(error) throw error
        if (snap.properties().name === undefined) {
          // The user logged in for the first time
          Appbase.ref('global/users').setEdge(refs.user,userId)
          // Set user's name
          refs.user.setData({
            name: userId
          })
          // Create vertices which will store user's followers, followings and tweets
          refs.user.setEdge(Appbase.create('misc',Appbase.uuid()),'tweets',function(error){
            if(error) throw error
            refs.user.setEdge(Appbase.create('misc',Appbase.uuid()),'followers', function(error){
              if(error) throw error
              refs.user.setEdge(Appbase.create('misc',Appbase.uuid()),'following', function(error){
                if(error) throw error
                //Set the flag true in userSession
                userSession.initComplete = true
                ready()
              })
            })
          })
        } else {
          //The user exists in Appbase
          userSession.initComplete = true
          ready()
        }
      })
    }
    data.addTweet = function(msg) {
      //Create a new 'tweet' vertex and store the tweet message
      var tweetRef = Appbase.create('tweet',Appbase.uuid())
      tweetRef.setData({ 'msg': msg, 'by': userSession.getUser() },function(error, tweetRef) {
        if(error) throw error
        //Add this tweet as an edge, in user's own tweets and global tweets.
        //We really don't care about the edge's name here
        var randomEdgeName = Appbase.uuid()
        refs.usersTweets.setEdge(tweetRef,randomEdgeName)
        refs.globalTweets.setEdge(tweetRef,randomEdgeName)
      })
    }
    // Checks whether provided userId is being followed by the logged in user
    data.isUserBeingFollowed = function(userId,callback){
      refs.usersFollowing.outVertex(userId).isValid(function(error, bool){
        if(error) throw error
        callback(bool)
      })
    }
    data.follow = function(userId) {
      refs.usersFollowing.setEdge(Appbase.ref('user/'+userId),userId)
      Appbase.ref('user/'+userId+'/followers').setEdge(refs.user,userSession.getUser())
    }
    data.unFollow = function(userId) {
      refs.usersFollowing.removeEdge(userId)
      Appbase.ref('user/'+userId+'/followers').removeEdge(userSession.getUser())
    }
    return data
  })
  // Stores logged in user's id.
  .factory('userSession',function() {
    var userSession = {}
    userSession.initComplete = false
    userSession.setUser = function(userId){
      localStorage.setItem("currentLoggedInUser", userId)
    }
    userSession.exit = function(){
      localStorage.removeItem("currentLoggedInUser")
    }
    userSession.getUser = function(){
      return localStorage.getItem("currentLoggedInUser")
    }
    return userSession
  })<commit_msg>Change to twitter app<commit_after>/* In this app $rootScope is mostly used for
 * changing the route and managing visibly of navigation bar.
 */
Appbase.credentials("twitter", "2cac84749bc429ad7017bb1685eafaf4");
angular.module('twitter',['ngRoute','ngAppbase'])
  .run(function($rootScope,userSession,$location) {
    $rootScope.exit = function() {
      userSession.exit()
      $location.path('/global')
    }
    $rootScope.gotoProfile = function(userId){
      $location.path('/profile/'+userId)
    }
    $rootScope.search = function(text){
      $location.path('/search/'+text)
    }
    $rootScope.goHome = function(feed){
      $location.path('/home/'+feed)
    }
    $rootScope.hideNav = function (){
      $rootScope.$broadcast('hideNav',[1])
    }
    $rootScope.showNav = function (){
      $rootScope.$broadcast('showNav')
    }
    $rootScope.load = function() {
      $location.path('/loading')
    }
  })
  // Route management
  .config(function($routeProvider){
    $routeProvider
      .when('/',
      {
        controller:'global',
        templateUrl:'views/global.html'
      }
    ).when('/loading',
      {
        controller:'loading',
        templateUrl:'views/loading.html'
      }
    ).when('/search/:text',
      {
        controller:'search',
        templateUrl:'views/search.html'
      }
    ).when('/profile/:userId',
      {
        controller:'profile',
        templateUrl:'views/profile.html'
      }
    ).when('/home/:feed',
      {
        controller:'home',
        templateUrl:'views/home.html'
      }
    ).otherwise({redirectTo:'/'})
  })
  /* Controller: global
   * Shows all tweets when no one is logged in
   */
  .controller('global', function ($scope, userSession, $location,$rootScope,$appbaseRef) {
    // Navigation bar shouldn't be visible if no one is logged in
    $rootScope.hideNav()

    // Called when the user enter a name, or the user is already logged in
    $scope.login = function() {
      userSession.setUser($scope.userId.replace(/ /g, "_"))
      $location.path('/loading')
    }
    // Check if a user is already logged in the session
    if( $scope.userId = userSession.getUser()){
      $scope.login()
    }
    //Show all tweets
    $appbaseRef('global/tweets').$bindEdges($scope,'tweets')
  })
  /* Controller: search
   * Search's for tweets in Appbase and shows results
   */
  .controller('search', function ($scope, $rootScope, $routeParams) {
    // Getting the 'query text' from route parameters
    $scope.currentQuery = $routeParams.text
    // Searching in the namespace: __tweet__ for vertices, which contain 'query text' in the property: __msg__
    Appbase.search('tweet',{text: $routeParams.text, properties:['msg']},function(error, array) {
      $scope.tweets = array
      $scope.$apply()
    })
  })
  /* Controller: Loading
   * It inits the __data__ factory, which is used everywhere in the app to fetch and set data from/to Appbase.
   * After the _init_ completes, it takes the user to _home_ screen, showing personal tweets of the user.
   */
  .controller('loading', function ($rootScope,$scope, userSession, data) {
    if(!userSession.getUser()){
      $rootScope.exit()
      return
    }
    data.init(function() {
      $scope.$apply(function() {
        $rootScope.goHome('personal')
      })
    })
  })
  /* Controller: navbar
   * Handles button clicks and visibility of buttons
   */
  .controller('navbar',function($scope,userSession,$location,$rootScope,$routeParams){
    $scope.bahar = true
    // Called when user enters a text in the search box and presses Enter key
    $scope.search = function() {
      $rootScope.search($scope.searchText)
      $scope.searchText = ''
    }
    $scope.$on('showNav',function() {
      $scope.bahar = false
    })
    $scope.$on('hideNav',function() {
      $scope.bahar = true
    })
    $scope.exit= function() {
      $rootScope.exit()
    }
    $scope.gotoProfile= function(userId){
      if(userId === undefined)
        var userId = userSession.getUser()
      $rootScope.gotoProfile(userId)
    }
    $scope.goHome = function(feed){
      $rootScope.goHome(feed)
    }
  })
  /* Controller: home
   * This is what the user sees first when logged in. It shows the personal and global tweet feeds
   * The personal tweet feed: shows tweets from people he follows
   * The global feed: tweets by everyone
   */
  .controller('home',function($scope,userSession,$location,$rootScope,$appbaseRef,$routeParams,data){
    // Check if the session is properly initiated,
    // i.e. the 'data' factory set the flag 'initComplete' in userSession
    if(!userSession.initComplete) {
      if(!userSession.getUser())
        $rootScope.exit()
      else
        $rootScope.load()
      return
    }
    $rootScope.showNav()
    //Get __feed__ from route parameters
    var feed = $routeParams.feed === undefined? 'global': $routeParams.feed
    $scope.tweets = []
    $scope.people = []
    $scope.userName = userSession.getUser()
    $scope.gotoProfile = $rootScope.gotoProfile
    //Show _People on Twitter_, user's _Followers_ and _Followings_
    $appbaseRef(data.refs.allUsers).$bindEdges($scope,'people')
    $appbaseRef(data.refs.usersFollowers).$bindEdges($scope,'followers')
    $appbaseRef(data.refs.usersFollowing).$bindEdges($scope,'following')

    //Called when user posts a new tweet
    $scope.addTweet = function() {
      data.addTweet($scope.msg)
      $scope.msg = ''
    }
    if(feed === 'global') {
      // Show all tweets
      $appbaseRef(data.refs.globalTweets).$bindEdges($scope,'tweets')
    } else {
      /* Fetch tweets of the people followed by the user. Every following's tweets are pushed into `arraysOfTweets` as an array,
       * and in the end, these arrays are merged into personalTweets by calling `personalTweets.concat.apply(personalTweets, arraysOfTweets)`
       * in _home.html_
       */
      $scope.personalTweets = []
      $scope.arraysOfTweets = []
      $scope.arraysOfTweets.push($appbaseRef('user/'+userSession.getUser()+'/tweets').$bindEdges($scope))
      var usrRef = Appbase.ref('user/'+userSession.getUser()+'/following')
      usrRef.on('edge_added',function(error, followUserRef) {
        if(error) throw error
        $scope.arraysOfTweets.push($appbaseRef(followUserRef).$outVertex('tweets').$bindEdges($scope))
      })
      $scope.$on('$destroy',function() {
        //Stop listening to user's followings when the view is destroyed.
        usrRef.off()
      })
    }
  })
  /* Controller: profile
   * Where a user's followings, followers and tweets are shown.
   * A user can also see other's profiles and choose to follow/unfollow the person from his/her profile.
   */
  .controller('profile',function($scope,userSession,$location,$rootScope,$routeParams,$appbaseRef,data){
    if(!userSession.initComplete) {
      if(!userSession.getUser())
        $rootScope.exit()
      else
        $rootScope.load()
      return
    }
    $rootScope.showNav()

    //Get the userId from route params
    var userId = $routeParams.userId
    $scope.userId = $routeParams.userId
    //Check whether this profile is of the logged in user
    $scope.isMe = userSession.getUser() === userId
    $scope.userName = $routeParams.userId
    $scope.isReady = false

    //Check whether this user is being followed by the logged in user
    // This has to be an async function, as it interacts with the Appbase server
    !$scope.isMe && data.isUserBeingFollowed(userId,function(boolean){
      //If true, _unfollow_ button will appear, otherwise _follow_ one
      $scope.isBeingFollowed = boolean
      //Show _follow_ or _unfollow_ buttons only when the data is arrived
      $scope.isReady = true
    })
    $scope.gotoProfile = $rootScope.gotoProfile
    $scope.follow = function(userId){
      $scope.isBeingFollowed = true
      data.follow(userId)
    }
    $scope.unFollow = function(userId){
      $scope.isBeingFollowed = false
      data.unFollow(userId)
    }
    $scope.addTweet = function() {
      data.addTweet($scope.msg)
      $scope.msg = ''
    }
    //Fetch user's followers, followings and tweets
    $appbaseRef('user/'+userId+'/followers').$bindEdges($scope,'followers')
    $appbaseRef('user/'+userId+'/following').$bindEdges($scope,'following')
    $appbaseRef('user/'+userId+'/tweets').$bindEdges($scope,'tweets')
  })
  /*
   * Factory: data
   * Stores frequently useful Appbase references and interacts with Appbase for data needs
   */
  .factory('data',function(userSession) {
    // Appbase references
    var refs = {
      globalTweets: Appbase.ref('global/tweets'),
      allUsers: Appbase.ref('global/users')
    }
    // Factory to be exported
    var data = {
      refs:refs
    }
    // Called when the user just logs in.
    // It sets required references and creates basic data for a new user
    data.init = function(ready) {
      var userId = userSession.getUser()
      refs.user = Appbase.create('user',userSession.getUser())
      refs.usersTweets = refs.user.outVertex('tweets')
      refs.usersFollowers = refs.user.outVertex('followers')
      refs.usersFollowing = refs.user.outVertex('following')
      refs.user.on('properties',function(error, ref, snap) {
        refs.user.off()
        if(error) throw error
        if (snap.properties().name === undefined) {
          // The user logged in for the first time
          Appbase.ref('global/users').setEdge(refs.user,userId)
          // Set user's name
          refs.user.setData({
            name: userId
          })
          // Create vertices which will store user's followers, followings and tweets
          refs.user.setEdge(Appbase.create('misc',Appbase.uuid()),'tweets',function(error){
            if(error) throw error
            refs.user.setEdge(Appbase.create('misc',Appbase.uuid()),'followers', function(error){
              if(error) throw error
              refs.user.setEdge(Appbase.create('misc',Appbase.uuid()),'following', function(error){
                if(error) throw error
                //Set the flag true in userSession
                userSession.initComplete = true
                ready()
              })
            })
          })
        } else {
          //The user exists in Appbase
          userSession.initComplete = true
          ready()
        }
      })
    }
    data.addTweet = function(msg) {
      //Create a new 'tweet' vertex and store the tweet message
      var tweetRef = Appbase.create('tweet',Appbase.uuid())
      tweetRef.setData({ 'msg': msg, 'by': userSession.getUser() },function(error, tweetRef) {
        if(error) throw error
        //Add this tweet as an edge, in user's own tweets and global tweets.
        //We really don't care about the edge's name here
        var randomEdgeName = Appbase.uuid()
        refs.usersTweets.setEdge(tweetRef,randomEdgeName)
        refs.globalTweets.setEdge(tweetRef,randomEdgeName)
      })
    }
    // Checks whether provided userId is being followed by the logged in user
    data.isUserBeingFollowed = function(userId,callback){
      refs.usersFollowing.outVertex(userId).isValid(function(error, bool){
        if(error) throw error
        callback(bool)
      })
    }
    data.follow = function(userId) {
      refs.usersFollowing.setEdge(Appbase.ref('user/'+userId),userId)
      Appbase.ref('user/'+userId+'/followers').setEdge(refs.user,userSession.getUser())
    }
    data.unFollow = function(userId) {
      refs.usersFollowing.removeEdge(userId)
      Appbase.ref('user/'+userId+'/followers').removeEdge(userSession.getUser())
    }
    return data
  })
  // Stores logged in user's id.
  .factory('userSession',function() {
    var userSession = {}
    userSession.initComplete = false
    userSession.setUser = function(userId){
      localStorage.setItem("currentLoggedInUser", userId)
    }
    userSession.exit = function(){
      localStorage.removeItem("currentLoggedInUser")
    }
    userSession.getUser = function(){
      return localStorage.getItem("currentLoggedInUser")
    }
    return userSession
  })<|endoftext|>


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

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { CORE_USER } from './constants';
const { createRegistrySelector } = Data;

// Actions
const CLEAR_PERMISSION_SCOPE_ERROR = 'CLEAR_PERMISSION_SCOPE_ERROR';
const SET_PERMISSION_SCOPE_ERROR = 'SET_PERMISSION_SCOPE_ERROR';
const RECEIVE_CAPABILITIES = 'RECEIVE_CAPABILITIES';

export const initialState = {
	permissionError: null,
	capabilities: undefined,
};

export const actions = {
	/**
	 * Clears the permission scope error, if one was previously set.
	 *
	 * @since 1.9.0
	 * @private
	 *
	 * @return {Object} Redux-style action.
	 */
	clearPermissionScopeError() {
		return {
			payload: {},
			type: CLEAR_PERMISSION_SCOPE_ERROR,
		};
	},

	/**
	 * Sets a permission error encountered by an API request.
	 *
	 * @since 1.9.0
	 * @private
	 *
	 * @param {Object} permissionError Permissions error object.
	 * @return {Object} Redux-style action.
	 */
	setPermissionScopeError( permissionError ) {
		invariant( permissionError, 'permissionError is required.' );

		return {
			payload: { permissionError },
			type: SET_PERMISSION_SCOPE_ERROR,
		};
	},

	/**
	 * Sets user capabilities.
	 *
	 * @since 1.13.0
	 * @private
	 *
	 * @param {Object} capabilities User capabilities.
	 * @return {Object} Redux-style action.
	 */
	receiveCapabilities( capabilities ) {
		return {
			type: RECEIVE_CAPABILITIES,
			payload: { capabilities },
		};
	},
};

export const controls = {};

export const reducer = ( state, { type, payload } ) => {
	switch ( type ) {
		case CLEAR_PERMISSION_SCOPE_ERROR: {
			return {
				...state,
				permissionError: null,
			};
		}

		case SET_PERMISSION_SCOPE_ERROR: {
			const { permissionError } = payload;

			return {
				...state,
				permissionError,
			};
		}

		case RECEIVE_CAPABILITIES: {
			const { capabilities } = payload;

			return {
				...state,
				capabilities,
			};
		}

		default: {
			return state;
		}
	}
};

export const resolvers = {
	*getCapabilities() {
		const registry = yield Data.commonActions.getRegistry();

		if ( registry.select( CORE_USER ).getCapabilities() ) {
			return;
		}

		if ( ! global._googlesitekitUserData?.permissions ) {
			global.console.error( 'Could not load core/user permissions.' );
		}

		yield actions.receiveCapabilities(
			global._googlesitekitUserData?.permissions
		);
	},
};

export const selectors = {
	/**
	 * Gets the most recent permission error encountered by this user.
	 *
	 * @since 1.9.0
	 * @private
	 *
	 * @param {Object} state Data store's state.
	 * @return {(Object|undefined)} Permission scope errors. Returns `null` if no error exists.
	 */
	getPermissionScopeError( state ) {
		const { permissionError } = state;
		return permissionError;
	},

	/**
	 * Gets capabilities of the current user.
	 *
	 * @since 1.13.0
	 *
	 * @param {Object} state Data store's state.
	 * @return {(Object|undefined)} Capabilities object. Returns undefined if it is not loaded yet.
	 */
	getCapabilities( state ) {
		const { capabilities } = state;
		return capabilities;
	},

	/**
	 * Checks if the current user has the specified capability or not.
	 *
	 * @since 1.13.0
	 *
	 * @param {Object} state      Data store's state.
	 * @param {string} capability Capability name to check.
	 * @param {Array}  args       List of rest of the arguments. Specifically one or many module slugs.
	 * @return {(boolean|undefined)} TRUE if the current user has this capability, otherwise FALSE. If capabilities ain't loaded yet, returns undefined.
	 */
	hasCapability: createRegistrySelector(
		( select ) => ( state, capability, ...args ) => {
			const capabilities = select( CORE_USER ).getCapabilities();

			if ( args.length > 0 ) {
				capability = `${ capability }::${ JSON.stringify( args ) }`;
			}

			if ( capabilities ) {
				return !! capabilities[ capability ];
			}

			return undefined;
		}
	),
};

export default {
	initialState,
	actions,
	controls,
	reducer,
	resolvers,
	selectors,
};
<commit_msg>Implement getViewableModules selector.<commit_after>/**
 * `core/user` data store: permission scopes.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { CORE_USER, PERMISSION_READ_SHARED_MODULE_DATA } from './constants';
import { CORE_MODULES } from '../../modules/datastore/constants';
const { createRegistrySelector } = Data;

// Actions
const CLEAR_PERMISSION_SCOPE_ERROR = 'CLEAR_PERMISSION_SCOPE_ERROR';
const SET_PERMISSION_SCOPE_ERROR = 'SET_PERMISSION_SCOPE_ERROR';
const RECEIVE_CAPABILITIES = 'RECEIVE_CAPABILITIES';

export const initialState = {
	permissionError: null,
	capabilities: undefined,
};

export const actions = {
	/**
	 * Clears the permission scope error, if one was previously set.
	 *
	 * @since 1.9.0
	 * @private
	 *
	 * @return {Object} Redux-style action.
	 */
	clearPermissionScopeError() {
		return {
			payload: {},
			type: CLEAR_PERMISSION_SCOPE_ERROR,
		};
	},

	/**
	 * Sets a permission error encountered by an API request.
	 *
	 * @since 1.9.0
	 * @private
	 *
	 * @param {Object} permissionError Permissions error object.
	 * @return {Object} Redux-style action.
	 */
	setPermissionScopeError( permissionError ) {
		invariant( permissionError, 'permissionError is required.' );

		return {
			payload: { permissionError },
			type: SET_PERMISSION_SCOPE_ERROR,
		};
	},

	/**
	 * Sets user capabilities.
	 *
	 * @since 1.13.0
	 * @private
	 *
	 * @param {Object} capabilities User capabilities.
	 * @return {Object} Redux-style action.
	 */
	receiveCapabilities( capabilities ) {
		return {
			type: RECEIVE_CAPABILITIES,
			payload: { capabilities },
		};
	},
};

export const controls = {};

export const reducer = ( state, { type, payload } ) => {
	switch ( type ) {
		case CLEAR_PERMISSION_SCOPE_ERROR: {
			return {
				...state,
				permissionError: null,
			};
		}

		case SET_PERMISSION_SCOPE_ERROR: {
			const { permissionError } = payload;

			return {
				...state,
				permissionError,
			};
		}

		case RECEIVE_CAPABILITIES: {
			const { capabilities } = payload;

			return {
				...state,
				capabilities,
			};
		}

		default: {
			return state;
		}
	}
};

export const resolvers = {
	*getCapabilities() {
		const registry = yield Data.commonActions.getRegistry();

		if ( registry.select( CORE_USER ).getCapabilities() ) {
			return;
		}

		if ( ! global._googlesitekitUserData?.permissions ) {
			global.console.error( 'Could not load core/user permissions.' );
		}

		yield actions.receiveCapabilities(
			global._googlesitekitUserData?.permissions
		);
	},
};

export const selectors = {
	/**
	 * Gets the most recent permission error encountered by this user.
	 *
	 * @since 1.9.0
	 * @private
	 *
	 * @param {Object} state Data store's state.
	 * @return {(Object|undefined)} Permission scope errors. Returns `null` if no error exists.
	 */
	getPermissionScopeError( state ) {
		const { permissionError } = state;
		return permissionError;
	},

	/**
	 * Gets capabilities of the current user.
	 *
	 * @since 1.13.0
	 *
	 * @param {Object} state Data store's state.
	 * @return {(Object|undefined)} Capabilities object. Returns undefined if it is not loaded yet.
	 */
	getCapabilities( state ) {
		const { capabilities } = state;
		return capabilities;
	},

	/**
	 * Gets viewable module slugs of the current user.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Object} state Data store's state.
	 * @return {(Array|undefined)} An array of viewable module slugs. `undefined` if `modules` are not loaded yet.
	 */
	getViewableModules: createRegistrySelector( ( select ) => () => {
		const modules = select( CORE_MODULES ).getModules();

		if ( modules === undefined ) {
			return undefined;
		}

		const moduleSlug = [];
		// eslint-disable-next-line no-unused-vars
		for ( const [ _, module ] of Object.entries( modules ) ) {
			const hasCapability = select( CORE_USER ).hasCapability(
				PERMISSION_READ_SHARED_MODULE_DATA,
				module.slug
			);

			if ( module.shareable && hasCapability ) {
				moduleSlug.push( module.slug );
			}
		}

		return moduleSlug;
	} ),

	/**
	 * Checks if the current user has the specified capability or not.
	 *
	 * @since 1.13.0
	 *
	 * @param {Object} state      Data store's state.
	 * @param {string} capability Capability name to check.
	 * @param {Array}  args       List of rest of the arguments. Specifically one or many module slugs.
	 * @return {(boolean|undefined)} TRUE if the current user has this capability, otherwise FALSE. If capabilities ain't loaded yet, returns undefined.
	 */
	hasCapability: createRegistrySelector(
		( select ) => ( state, capability, ...args ) => {
			const capabilities = select( CORE_USER ).getCapabilities();

			if ( args.length > 0 ) {
				capability = `${ capability }::${ JSON.stringify( args ) }`;
			}

			if ( capabilities ) {
				return !! capabilities[ capability ];
			}

			return undefined;
		}
	),
};

export default {
	initialState,
	actions,
	controls,
	reducer,
	resolvers,
	selectors,
};
<|endoftext|>


<commit_before>var bf = require("../bloomfilter"),
    BloomFilter = bf.BloomFilter,
    fnv_1a = bf.fnv_1a,
    fnv_1a_b = bf.fnv_1a_b;

var vows = require("vows"),
    assert = require("assert");

var suite = vows.describe("bloomfilter");

var jabberwocky = "`Twas brillig, and the slithy toves\n  Did gyre and gimble in the wabe:\nAll mimsy were the borogoves,\n  And the mome raths outgrabe.\n\n\"Beware the Jabberwock, my son!\n  The jaws that bite, the claws that catch!\nBeware the Jubjub bird, and shun\n  The frumious Bandersnatch!\"\n\nHe took his vorpal sword in hand:\n  Long time the manxome foe he sought --\nSo rested he by the Tumtum tree,\n  And stood awhile in thought.\n\nAnd, as in uffish thought he stood,\n  The Jabberwock, with eyes of flame,\nCame whiffling through the tulgey wood,\n  And burbled as it came!\n\nOne, two! One, two! And through and through\n  The vorpal blade went snicker-snack!\nHe left it dead, and with its head\n  He went galumphing back.\n\n\"And, has thou slain the Jabberwock?\n  Come to my arms, my beamish boy!\nO frabjous day! Callooh! Callay!'\n  He chortled in his joy.\n\n`Twas brillig, and the slithy toves\n  Did gyre and gimble in the wabe;\nAll mimsy were the borogoves,\n  And the mome raths outgrabe.";

suite.addBatch({
  "bloom filter": {
    "basic": function() {
      var f = new BloomFilter(1000, 4),
          n1 = "Bess",
          n2 = "Jane";
      f.add(n1);
      assert.equal(f.test(n1), true);
      assert.equal(f.test(n2), false);
    },
    "jabberwocky": function() {
      var f = new BloomFilter(1000, 4),
          n1 = jabberwocky,
          n2 = jabberwocky + "\n";
      f.add(n1);
      assert.equal(f.test(n1), true);
      assert.equal(f.test(n2), false);
    },
    "basic uint32": function() {
      var f = new BloomFilter(1000, 4),
          n1 = "\u100",
          n2 = "\u101",
          n3 = "\u103";
      f.add(n1);
      assert.equal(f.test(n1), true);
      assert.equal(f.test(n2), false);
      assert.equal(f.test(n3), false);
    },
    "wtf": function() {
      var f = new BloomFilter(20, 10);
      assert.equal(f.locations("wtf").length, 10);
    }
  }
});

suite.export(module);
<commit_msg>Better test.<commit_after>var bf = require("../bloomfilter"),
    BloomFilter = bf.BloomFilter,
    fnv_1a = bf.fnv_1a,
    fnv_1a_b = bf.fnv_1a_b;

var vows = require("vows"),
    assert = require("assert");

var suite = vows.describe("bloomfilter");

var jabberwocky = "`Twas brillig, and the slithy toves\n  Did gyre and gimble in the wabe:\nAll mimsy were the borogoves,\n  And the mome raths outgrabe.\n\n\"Beware the Jabberwock, my son!\n  The jaws that bite, the claws that catch!\nBeware the Jubjub bird, and shun\n  The frumious Bandersnatch!\"\n\nHe took his vorpal sword in hand:\n  Long time the manxome foe he sought --\nSo rested he by the Tumtum tree,\n  And stood awhile in thought.\n\nAnd, as in uffish thought he stood,\n  The Jabberwock, with eyes of flame,\nCame whiffling through the tulgey wood,\n  And burbled as it came!\n\nOne, two! One, two! And through and through\n  The vorpal blade went snicker-snack!\nHe left it dead, and with its head\n  He went galumphing back.\n\n\"And, has thou slain the Jabberwock?\n  Come to my arms, my beamish boy!\nO frabjous day! Callooh! Callay!'\n  He chortled in his joy.\n\n`Twas brillig, and the slithy toves\n  Did gyre and gimble in the wabe;\nAll mimsy were the borogoves,\n  And the mome raths outgrabe.";

suite.addBatch({
  "bloom filter": {
    "basic": function() {
      var f = new BloomFilter(1000, 4),
          n1 = "Bess",
          n2 = "Jane";
      f.add(n1);
      assert.equal(f.test(n1), true);
      assert.equal(f.test(n2), false);
    },
    "jabberwocky": function() {
      var f = new BloomFilter(1000, 4),
          n1 = jabberwocky,
          n2 = jabberwocky + "\n";
      f.add(n1);
      assert.equal(f.test(n1), true);
      assert.equal(f.test(n2), false);
    },
    "basic uint32": function() {
      var f = new BloomFilter(1000, 4),
          n1 = "\u100",
          n2 = "\u101",
          n3 = "\u103";
      f.add(n1);
      assert.equal(f.test(n1), true);
      assert.equal(f.test(n2), false);
      assert.equal(f.test(n3), false);
    },
    "wtf": function() {
      var f = new BloomFilter(20, 10);
      f.add("abc");
      assert.equal(f.test("wtf"), false);
    }
  }
});

suite.export(module);
<|endoftext|>


<commit_before>'use strict';

var copy        = require('es5-ext/lib/Object/copy')
  , d           = require('es5-ext/lib/Object/descriptor')
  , extend      = require('es5-ext/lib/Object/extend')
  , dispatchEvt = require('dom-ext/lib/HTMLElement/prototype/dispatch-event-2')
  , Db          = require('dbjs')
  , DOMInput    = require('./input')
  , eventOpts   = require('../_event-options')

  , getInputValue =
	Object.getOwnPropertyDescriptor(DOMInput.prototype, 'inputValue').get
  , Input;

module.exports = Input = function (document, ns/*, options*/) {
	DOMInput.apply(this, arguments);
	this.dom.addEventListener('input', this.onChange, false);
};

Input.prototype = Object.create(DOMInput.prototype, {
	constructor: d(Input),
	controlAttributes: d(extend(copy(DOMInput.prototype.controlAttributes),
		{ cols: true, inputmode: true, maxlength: true, placeholder: true,
			readonly: true, required: true, rows: true, wrap: true })),
	dbAttributes: d(extend(copy(DOMInput.prototype.dbAttributes),
		{ max: 'maxlength', inputPlaceholder: 'placeholder', required: true })),
	_render: d(function () {
		this.control = this.dom = this.document.createElement('textarea');
		this.dom.appendChild(this.document.createTextNode(''));
	}),
	value: d.gs(getInputValue, function (nu) {
		var old = this.inputValue;
		if (this._value !== nu) this.control.firstChild.data = this._value = nu;
		if (nu !== old) {
			this.control.value = nu;
			try {
				dispatchEvt.call(this.control, 'change', eventOpts);
			} catch (ignore) {}
		} else {
			this.onChange();
		}
	})
});

Object.defineProperty(Db.Base, 'DOMTextarea', d(Input));
<commit_msg>Fix value resolution for textarea fields<commit_after>'use strict';

var copy        = require('es5-ext/lib/Object/copy')
  , d           = require('es5-ext/lib/Object/descriptor')
  , extend      = require('es5-ext/lib/Object/extend')
  , dispatchEvt = require('dom-ext/lib/HTMLElement/prototype/dispatch-event-2')
  , Db          = require('dbjs')
  , DOMInput    = require('./input')
  , eventOpts   = require('../_event-options')

  , getInputValue =
	Object.getOwnPropertyDescriptor(DOMInput.prototype, 'inputValue').get
  , Input;

module.exports = Input = function (document, ns/*, options*/) {
	DOMInput.apply(this, arguments);
	this.dom.addEventListener('input', this.onChange, false);
};

Input.prototype = Object.create(DOMInput.prototype, {
	constructor: d(Input),
	controlAttributes: d(extend(copy(DOMInput.prototype.controlAttributes),
		{ cols: true, inputmode: true, maxlength: true, placeholder: true,
			readonly: true, required: true, rows: true, wrap: true })),
	dbAttributes: d(extend(copy(DOMInput.prototype.dbAttributes),
		{ max: 'maxlength', inputPlaceholder: 'placeholder', required: true })),
	_render: d(function () {
		this.control = this.dom = this.document.createElement('textarea');
		this.dom.appendChild(this.document.createTextNode(''));
	}),
	inputValue: d.gs(getInputValue, function (nu) {
		var old = this.inputValue;
		if (this._value !== nu) this.control.firstChild.data = this._value = nu;
		if (nu !== old) {
			this.control.value = nu;
			try {
				dispatchEvt.call(this.control, 'change', eventOpts);
			} catch (ignore) {}
		} else {
			this.onChange();
		}
	})
});

Object.defineProperty(Db.Base, 'DOMTextarea', d(Input));
<|endoftext|>


<commit_before>'use strict';

var BinWrapper = require('bin-wrapper');
var path = require('path');
var pkg = require('../package.json');
var url = 'https://raw.github.com/imagemin/optipng-bin/v' + pkg.version + '/vendor/';

module.exports = new BinWrapper()
	.src(url + 'osx/optipng', 'darwin')
	.src(url + 'linux/x86/optipng', 'linux', 'x86')
	.src(url + 'linux/x64/optipng', 'linux', 'x64')
	.src(url + 'freebsd/optipng', 'freebsd')
	.src(url + 'sunos/x86/optipng', 'sunos', 'x86')
	.src(url + 'sunos/x64/optipng', 'sunos', 'x64')
	.src(url + 'win/optipng.exe', 'win32')
	.dest(path.join(__dirname, '../vendor'))
	.use(process.platform === 'win32' ? 'optipng.exe' : 'optipng')
	.version('>=0.7.5');
<commit_msg>Fix URL<commit_after>'use strict';

var BinWrapper = require('bin-wrapper');
var path = require('path');
var pkg = require('../package.json');
var url = 'https://raw.github.com/imagemin/optipng-bin/' + pkg.version + '/vendor/';

module.exports = new BinWrapper()
	.src(url + 'osx/optipng', 'darwin')
	.src(url + 'linux/x86/optipng', 'linux', 'x86')
	.src(url + 'linux/x64/optipng', 'linux', 'x64')
	.src(url + 'freebsd/optipng', 'freebsd')
	.src(url + 'sunos/x86/optipng', 'sunos', 'x86')
	.src(url + 'sunos/x64/optipng', 'sunos', 'x64')
	.src(url + 'win/optipng.exe', 'win32')
	.dest(path.join(__dirname, '../vendor'))
	.use(process.platform === 'win32' ? 'optipng.exe' : 'optipng')
	.version('>=0.7.5');
<|endoftext|>


<commit_before>function encrypt(text, pass) {
  //console.log('pass:' + pass + ' encrypt IN:' + text);
  var key = Sha256.hash(pass);
  var encrypted = Aes.Ctr.encrypt(text, key, 256);
  //console.log('encrypt OUT:' + encrypted);
  return encrypted;
}

function decrypt (text, pass) {
  //console.log('pass:' + pass + ' decrypt IN:' + text);
  var key = Sha256.hash(pass);
  var decrypted = Aes.Ctr.decrypt(text, key, 256);
  //console.log('decrypt OUT:' + decrypted);
  return decrypted;
}

function backToTop() {
  $("html, body").animate({ scrollTop: 0 }, "slow");
}

function passwordsMatch() {
  console.log("passwordsMatch()");

  if( $('#password').val() == $('#password2').val() ) {

    $('#passGroup').removeClass("has-error");
    $('#passwordError').addClass("hidden");

    return true;
  }

  $('#passGroup').addClass("has-error");
  $('#passwordError').removeClass("hidden");

  backToTop();

  return false;
}

function onMessageChange() {
    console.log("onMessageChange()");
    var m = $('#message');

    $("#count").text( m.val().length  );

    m.autosize({ append: '\n'});
    m.trigger('autosize.resize');
}

function messageUpdated() {
  $('#message').select();
  onMessageChange();
}

function clearMessage() {
  $('#message').val('');
  onMessageChange();
}

function pageEncrypt() {
  console.log("pageEncrypt()");
  if ( passwordsMatch() ) {
    $('#message').val( encrypt( $('#message').val(), $('#password').val() ) );
    messageUpdated();
  }
}

function pageDecrypt() {
  console.log("pageDecrypt()");
  if( passwordsMatch() ) {
    $('#message').val( decrypt( $('#message').val(), $('#password').val() ) );
    messageUpdated();
  }
}

$( function() {

  $("#message").change( onMessageChange );
  $("#message").keyup( onMessageChange );

  $('#encrypt').click( pageEncrypt );
  $('#decrypt').click( pageDecrypt );

  $('#backToTop').click( backToTop );
  $('#reset').click( clearMessage );

  onMessageChange();

  $('#splashscreen').delay( 1000 ).fadeOut('slow');

  options = {
    success: function(files) {
        // name, link, bytes, icon, thumbnailLink
        alert("Here's the file link: " + files[0].link)
        $('#message').val( files[0].bytes );
    },
    cancel: function() {

    },
    linkType: "direct", // or "direct"
    multiselect: false, // or true
    extensions: ['.md', '.txt', '.markdown', '.rsa'],
  };

  var button = Dropbox.createChooseButton(options);
  alert(button)
  $('container').append(button);

  console.log('Page loaded');
});
<commit_msg>Update app.js<commit_after>function encrypt(text, pass) {
  //console.log('pass:' + pass + ' encrypt IN:' + text);
  var key = Sha256.hash(pass);
  var encrypted = Aes.Ctr.encrypt(text, key, 256);
  //console.log('encrypt OUT:' + encrypted);
  return encrypted;
}

function decrypt (text, pass) {
  //console.log('pass:' + pass + ' decrypt IN:' + text);
  var key = Sha256.hash(pass);
  var decrypted = Aes.Ctr.decrypt(text, key, 256);
  //console.log('decrypt OUT:' + decrypted);
  return decrypted;
}

function backToTop() {
  $("html, body").animate({ scrollTop: 0 }, "slow");
}

function passwordsMatch() {
  console.log("passwordsMatch()");

  if( $('#password').val() == $('#password2').val() ) {

    $('#passGroup').removeClass("has-error");
    $('#passwordError').addClass("hidden");

    return true;
  }

  $('#passGroup').addClass("has-error");
  $('#passwordError').removeClass("hidden");

  backToTop();

  return false;
}

function onMessageChange() {
    console.log("onMessageChange()");
    var m = $('#message');

    $("#count").text( m.val().length  );

    m.autosize({ append: '\n'});
    m.trigger('autosize.resize');
}

function messageUpdated() {
  $('#message').select();
  onMessageChange();
}

function clearMessage() {
  $('#message').val('');
  onMessageChange();
}

function pageEncrypt() {
  console.log("pageEncrypt()");
  if ( passwordsMatch() ) {
    $('#message').val( encrypt( $('#message').val(), $('#password').val() ) );
    messageUpdated();
  }
}

function pageDecrypt() {
  console.log("pageDecrypt()");
  if( passwordsMatch() ) {
    $('#message').val( decrypt( $('#message').val(), $('#password').val() ) );
    messageUpdated();
  }
}

$( function() {

  $("#message").change( onMessageChange );
  $("#message").keyup( onMessageChange );

  $('#encrypt').click( pageEncrypt );
  $('#decrypt').click( pageDecrypt );

  $('#backToTop').click( backToTop );
  $('#reset').click( clearMessage );

  onMessageChange();

  $('#splashscreen').delay( 1000 ).fadeOut('slow');

  options = {
    success: function(files) {
        // name, link, bytes, icon, thumbnailLink
        alert("Here's the file link: " + files[0].link)
        $('#message').val( files[0].bytes );
    },
    cancel: function() {

    },
    linkType: "direct", // or "direct"
    multiselect: false, // or true
    extensions: ['.md', '.txt', '.markdown', '.rsa'],
  };

  var button = Dropbox.createChooseButton(options);
  var button = Dropbox.createChooseButton(options);
  document.getElementById("container").appendChild(button);

  console.log('Page loaded');
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*

 Usage:
 scripts/gen_keys.js

 Will create these files

 ./config/key.json
 ./config/oldKey.json

 If these files already exist, this script will show an error message
 and exit. You must remove both keys if you want to generate a new
 keypair.
 */

const fs = require('fs');
const assert = require('assert');
const generateRSAKeypair = require('keypair');
const JwTool = require('fxa-jwtool');

const keyPath = './config/key.json';
const oldKeyPath = './config/oldKey.json';

try {
  var keysExist = fs.existsSync(keyPath) && fs.existsSync(oldKeyPath);
  assert(!keysExist, 'keys already exists');
} catch (e) {
  process.exit();
}

function main(cb) {
  var privKey = JwTool.JWK.fromPEM(generateRSAKeypair().private, {
    kid: '2015.12.16-1'
  });

  try {
    fs.mkdirSync('./config');
  } catch (accessEx) {

  }

  fs.writeFileSync(keyPath, JSON.stringify(privKey.toJSON(), undefined, 2));
  console.log('Key saved:', keyPath); //eslint-disable-line no-console

  // The "old key" is not used to sign anything, so we don't need to store
  // the private component, we just need to serve the public component
  // so that old signatures can be verified correctly.
  var pubKey = JwTool.JWK.fromPEM(generateRSAKeypair().public, {
    kid: '2015.12.16-2'
  });
  fs.writeFileSync(oldKeyPath, JSON.stringify(pubKey.toJSON(), undefined, 2));
  console.log('OldKey saved:', oldKeyPath); //eslint-disable-line no-console
  cb();
}

module.exports = main;

if (require.main === module) {
  main(function () {
  });
}
<commit_msg>fix(keys): Generate unique 'kid' field when regenerating JWK keys<commit_after>#!/usr/bin/env node

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*

 Usage:
 scripts/gen_keys.js

 Will create these files

 ./config/key.json
 ./config/oldKey.json

 If these files already exist, this script will show an error message
 and exit. You must remove both keys if you want to generate a new
 keypair.
 */

const fs = require('fs');
const assert = require('assert');
const crypto = require('crypto');
const generateRSAKeypair = require('keypair');
const JwTool = require('fxa-jwtool');

const keyPath = './config/key.json';
const oldKeyPath = './config/oldKey.json';

try {
  var keysExist = fs.existsSync(keyPath) && fs.existsSync(oldKeyPath);
  assert(!keysExist, 'keys already exists');
} catch (e) {
  process.exit();
}

// Generate a unique key id using hash of public key, and timestamp.
// This comes out like "2017-01-23-ebe69008de771d62cd1cadf9faa6daae".
function makeKeyId(kp) {
  return [
    (new Date()).toISOString().slice(0, 10) + '-' +
    crypto.createHash('sha256').update(kp.public).digest('hex').slice(0, 32)
  ].join('-');
}

function main(cb) {
  var kp = generateRSAKeypair();
  var privKey = JwTool.JWK.fromPEM(kp.private, {
    kid: makeKeyId(kp)
  });

  try {
    fs.mkdirSync('./config');
  } catch (accessEx) {

  }

  fs.writeFileSync(keyPath, JSON.stringify(privKey.toJSON(), undefined, 2));
  console.log('Key saved:', keyPath); //eslint-disable-line no-console

  // The "old key" is not used to sign anything, so we don't need to store
  // the private component, we just need to serve the public component
  // so that old signatures can be verified correctly.
  kp = generateRSAKeypair();
  var pubKey = JwTool.JWK.fromPEM(kp.public, {
    kid: makeKeyId(kp)
  });
  fs.writeFileSync(oldKeyPath, JSON.stringify(pubKey.toJSON(), undefined, 2));
  console.log('OldKey saved:', oldKeyPath); //eslint-disable-line no-console
  cb();
}

module.exports = main;

if (require.main === module) {
  main(function () {
  });
}
<|endoftext|>


<commit_before>/**
 * @fileoverview This file provides a "elevation" directive. This directive is
 * used to insert Elevation information into the HTML page.
 * Example:
 *
 * <app-elevation app-elevation-map="::mainCtrl.map"map></app-elevation>
 *
 * Note the use of the one-time binding operator (::) in the map expression.
 * One-time binding is used because we know the map is not going to change
 * during the lifetime of the application.
 *
 */
goog.provide('app.elevationDirective');

goog.require('app');
goog.require('app.projections');
goog.require('ngeo.Debounce');

/**
 * @return {angular.Directive} The Directive Object Definition.
 * @ngInject
 */
app.elevationDirective = function() {
  return {
    restrict: 'E',
    scope: {
      'map': '=appElevationMap'
    },
    controller: 'AppElevationController',
    controllerAs: 'ctrl',
    bindToController: true,
    template: '' +
                'Elevation: {{elevation}} m'
  };
};

app.module.directive('appElevation', app.elevationDirective);

/**
 * @ngInject
 * @constructor
 */
app.ElevationDirectiveController = function($scope, $http, ngeoDebounce) {
  this['map'].on('pointermove',
      ngeoDebounce(function(e) {
        var lonlat = /** @type {ol.Coordinate} */
            (ol.proj.transform(e.coordinate,
                   this.getView().getProjection(), 'EPSG:2169'));
        $http({
          url: 'raster',
          method: 'GET',
          params: {'lon': lonlat[0], 'lat': lonlat[1]}
        }).
            success(function(data) {
              if (data['dhm'] > 0) {
                $scope['elevation'] = parseInt(data['dhm'] / 100 , 0);
              } else {
                $scope['elevation'] = 'N/A';
              }
            });
      }, 300, true));
};

app.module.controller('AppElevationController',
    app.ElevationDirectiveController);
<commit_msg>taking into account code comments by @elemoine & linter<commit_after>/**
 * @fileoverview This file provides a "elevation" directive. This directive is
 * used to insert Elevation information into the HTML page.
 * Example:
 *
 * <app-elevation app-elevation-map="::mainCtrl.map"map></app-elevation>
 *
 * Note the use of the one-time binding operator (::) in the map expression.
 * One-time binding is used because we know the map is not going to change
 * during the lifetime of the application.
 *
 */
goog.provide('app.elevationDirective');

goog.require('app');
goog.require('app.projections');
goog.require('ngeo.Debounce');

/**
 * @return {angular.Directive} The Directive Object Definition.
 * @ngInject
 */
app.elevationDirective = function() {
  return {
    restrict: 'E',
    scope: {
      'map': '=appElevationMap'
    },
    controller: 'AppElevationController',
    controllerAs: 'ctrl',
    bindToController: true,
    template: '' +
        'Elevation: {{ctrl.elevation}} m'
  };
};

app.module.directive('appElevation', app.elevationDirective);

/**
 * @ngInject
 * @constructor
 */
app.ElevationDirectiveController = function($http, ngeoDebounce) {
  var that = this;
  this['map'].on('pointermove',
      ngeoDebounce(
      function(e) {
        var lonlat = /** @type {ol.Coordinate} */
                (ol.proj.transform(e.coordinate,
                   this.getView().getProjection(), 'EPSG:2169'));
            $http({
              url: 'raster',
              method: 'GET',
              params: {'lon': lonlat[0], 'lat': lonlat[1]}
            }).
            success(goog.bind(function(data) {
              this['elevation'] = data['dhm'] > 0 ? parseInt(data['dhm'] / 100, 0) : 'N/A';
            }, that));
      }, 300, true));
};

app.module.controller('AppElevationController',
    app.ElevationDirectiveController);
<|endoftext|>


<commit_before>//$(document).on('DOMContentLoaded', function() {
//  var box = $('#box');
//  console.log('box ready', box);
//  TweenLite.to(box, 3, { x: 600 });
//  TweenLite.to(box, 2, {top:300 });
//  TweenLite.to(box, 2, { opacity:0 });
//});

document.addEventListener('DOMContentLoaded', function() {
  var box = document.getElementById('box');
  TweenLite.to(box, 3, { x: 600 });
  console.log('animating maybe', box);
})
<commit_msg>Extracted the animation options into its own object<commit_after>$(document).on('DOMContentLoaded', function() {
  // Animate the box to 600px to the right in 3 seconds
  var animationOptions = {
    x: 600,
    onComplete: function() {
      TweenLite.to('.box', 3, { y: 200 });
    }
  }
  TweenLite.to('.box', 1, animationOptions);
});
<|endoftext|>


<commit_before>import { h, Component } from 'preact';
import axios from 'axios';
import Title from './title';

export default class Footer extends Component {

  state = {
    contributors: []
  };

  fetchContributers() {
    axios.get('https://api.github.com/repos/ivanseed/gitstats/contributors')
      .then(response => {
        this.setState({ contributors: response.data })
      })
      .catch(err => {
        console.log('gota error :(')
      })
  }

  componentWillMount = this.fetchContributers;

  render(props, state) {
    return (

              <Title />

            Special thanks to all contributors that made this project possible!

              {state.contributors.map((contributor, i) =>

                  <a href={`https://github.com/${contributor.login}`}>
                    {contributor.login}

                  {/* Don't render comma on final name */}
                  { i + 1 === state.contributors.length ? '' : ', '}

              )}

    );
  }
}
<commit_msg>Added footer links for copyright and repo<commit_after>import { h, Component } from 'preact';
import axios from 'axios';
import Title from './title';

export default class Footer extends Component {

  state = {
    contributors: []
  };

  fetchContributers() {
    axios.get('https://api.github.com/repos/ivanseed/gitstats/contributors')
      .then(response => {
        this.setState({ contributors: response.data })
      })
      .catch(err => {
        console.log('gota error :(')
      })
  }

  componentWillMount = this.fetchContributers;

  render(props, state) {
    return (

Fork me on GitHub!

MIT License Copyright©

            Special thanks to all contributors that made this project possible!

              {state.contributors.map((contributor, i) =>

                  <a href={`https://github.com/${contributor.login}`}>
                    {contributor.login}

                  {/* Don't render comma on final name */}
                  { i + 1 === state.contributors.length ? '' : ', '}

              )}

    );
  }
}
<|endoftext|>


<commit_before>import React from 'react'
import IconButton from '@material-ui/core/IconButton'
import Typography from '@material-ui/core/Typography'
import Avatar from '@material-ui/core/Avatar'
import Toolbar from '@material-ui/core/Toolbar'
import AppBar from '@material-ui/core/AppBar'
import Menu from '@material-ui/core/Menu'
import MenuItem from '@material-ui/core/MenuItem'
import Divider from '@material-ui/core/Divider'
import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText'
import { withStyles } from '@material-ui/core/styles'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import gravatar from 'gravatar'
import Raven from 'raven-js'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

import { library as faLibrary } from '@fortawesome/fontawesome'
import faSignOutAlt from '@fortawesome/fontawesome-free-solid/faSignOutAlt'
import faBug from '@fortawesome/fontawesome-free-solid/faBug'

faLibrary.add(faSignOutAlt, faBug)

import BusyIndicator from './BusyIndicator'
import { logout } from '../../actions'
import { getCurrentUser, getLoggedIn } from '../../selectors/auth'
import { withProvider, Model } from '../../store'
import DialogOpener from '../DialogOpener'

const People = new Model('people')

const mapStateToProps = state => {
    const currentUser = getCurrentUser(state)
    const currentPerson = People.immutableSelect(state).get(currentUser.email)
    return {
        logged_in: getLoggedIn(state),
        current_user: currentUser,
        currentPerson
    }
}

const mapDispatchToProps = dispatch => {
    return bindActionCreators({logout}, dispatch)
}

const doReport = () => {
    Raven.captureMessage('Manual report')
    Raven.showReportDialog()
}

export const AppMenu = props => (
    <Menu open={props.open} onClose={props.onClose}>
        <MenuItem onClick={props.onLogout}>
            <ListItemIcon><FontAwesomeIcon icon={['fas', 'sign-out-alt']} /></ListItemIcon>
            <ListItemText>Logout</ListItemText>
        </MenuItem>
        <Divider />
        <MenuItem onClick={() => {doReport();props.onClose()}}>
            <ListItemIcon><FontAwesomeIcon icon={['fas', 'bug']} /></ListItemIcon>
            <ListItemText>Report a bug</ListItemText>
        </MenuItem>
    </Menu>
)

export const OrganizerAppBar = (props) => (
    <AppBar style={{position: 'initial'}}>
        <Toolbar>
            <DialogOpener>
                {(doOpen, doClose, isOpen) => (
                    <React.Fragment>
                        <IconButton onClick={doOpen} ><Avatar src={gravatar.url(props.current_user.email, {s: 32, d: 'retro'})}/></IconButton>
                        <AppMenu open={isOpen} onClose={doClose} onLogout={props.logout} />
                    </React.Fragment>
                )}
            </DialogOpener>

                <Typography color="inherit" variant="title">{props.currentPerson.name || ''}</Typography>
                <Typography color="inherit" variant="subheading">{props.current_user.email} - {props.currentPerson.twelve_month_event_count} events</Typography>

            <BusyIndicator />
        </Toolbar>
    </AppBar>
)

OrganizerAppBar.defaultProps = {
    currentPerson: {},
    current_user: {},
    classes: {},
    logged_in: false
}

const styles = {
    flex: {
        flexGrow: 1
    }
}

export default withProvider(withStyles(styles)(connect(mapStateToProps, mapDispatchToProps)(OrganizerAppBar)))
<commit_msg>components: chrome: organizerappbar: add admin link to menu if they have access<commit_after>import React from 'react'
import IconButton from '@material-ui/core/IconButton'
import Typography from '@material-ui/core/Typography'
import Avatar from '@material-ui/core/Avatar'
import Toolbar from '@material-ui/core/Toolbar'
import AppBar from '@material-ui/core/AppBar'
import Menu from '@material-ui/core/Menu'
import MenuItem from '@material-ui/core/MenuItem'
import Divider from '@material-ui/core/Divider'
import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText'
import { withStyles } from '@material-ui/core/styles'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import gravatar from 'gravatar'
import Raven from 'raven-js'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

import { library as faLibrary } from '@fortawesome/fontawesome'
import faSignOutAlt from '@fortawesome/fontawesome-free-solid/faSignOutAlt'
import faBug from '@fortawesome/fontawesome-free-solid/faBug'
import faExternalLinkAlt from '@fortawesome/fontawesome-free-solid/faExternalLinkAlt'

faLibrary.add(faSignOutAlt, faBug, faExternalLinkAlt)

import BusyIndicator from './BusyIndicator'
import { logout } from '../../actions'
import { getCurrentUser, getLoggedIn } from '../../selectors/auth'
import { withProvider, Model } from '../../store'
import DialogOpener from '../DialogOpener'

const People = new Model('people')

const mapStateToProps = state => {
    const currentUser = getCurrentUser(state)
    const currentPerson = People.immutableSelect(state).get(currentUser.email)
    return {
        logged_in: getLoggedIn(state),
        current_user: currentUser,
        currentPerson
    }
}

const mapDispatchToProps = dispatch => {
    return bindActionCreators({logout}, dispatch)
}

const doReport = () => {
    Raven.captureMessage('Manual report')
    Raven.showReportDialog()
}

export const AppMenu = props => (
    <Menu open={props.open} onClose={props.onClose}>
        <MenuItem onClick={props.onLogout}>
            <ListItemIcon><FontAwesomeIcon icon={['fas', 'sign-out-alt']} /></ListItemIcon>
            <ListItemText>Logout</ListItemText>
        </MenuItem>
        {props.current_user.is_staff ? <MenuItem onClick={() => {window.location = '/admin/'}}>
            <ListItemIcon><FontAwesomeIcon icon={['fas', 'external-link-alt']} /></ListItemIcon>
            <ListItemText>Administration</ListItemText>
        </MenuItem> : null }
        <Divider />
        <MenuItem onClick={() => {doReport();props.onClose()}}>
            <ListItemIcon><FontAwesomeIcon icon={['fas', 'bug']} /></ListItemIcon>
            <ListItemText>Report a bug</ListItemText>
        </MenuItem>
    </Menu>
)

export const OrganizerAppBar = (props) => (
    <AppBar style={{position: 'initial'}}>
        <Toolbar>
            <DialogOpener>
                {(doOpen, doClose, isOpen) => (
                    <React.Fragment>
                        <IconButton onClick={doOpen} ><Avatar src={gravatar.url(props.current_user.email, {s: 32, d: 'retro'})}/></IconButton>
                        <AppMenu current_user={props.current_user} open={isOpen} onClose={doClose} onLogout={props.logout} />
                    </React.Fragment>
                )}
            </DialogOpener>

                <Typography color="inherit" variant="title">{props.currentPerson.name || ''}</Typography>
                <Typography color="inherit" variant="subheading">{props.current_user.email} - {props.currentPerson.twelve_month_event_count} events</Typography>

            <BusyIndicator />
        </Toolbar>
    </AppBar>
)

OrganizerAppBar.defaultProps = {
    currentPerson: {},
    current_user: {},
    classes: {},
    logged_in: false
}

const styles = {
    flex: {
        flexGrow: 1
    }
}

export default withProvider(withStyles(styles)(connect(mapStateToProps, mapDispatchToProps)(OrganizerAppBar)))
<|endoftext|>


<commit_before>define(function(require){
    var fromColor = new THREE.Color(0xffb400);
    var toColor = new THREE.Color(0x51c8ff);

    var scene = new THREE.Object3D;
    var camera = new THREE.PerspectiveCamera(65, 16 / 9, 0.1, 5000);
    var Timer = require("Timer");
    var particleSpeed = 0.05;

    var StarField = require("component/starfield");
    scene.add(StarField.create(33));

    var sparkTexture = THREE.ImageUtils.loadTexture("images/spark.png");

    var particleSystem = createParticleSystem();
    scene.add(particleSystem);

    camera.position.set(0, 10, 30);
    camera.lookAt(particleSystem.position);

    var timer = new Timer();
    var flash = 1;
    return{
        scene: scene,
        camera: camera,
        render: function(time){
            var passed = timer.getPassed(time);
            _.each(particleSystem.geometry.vertices, function(vert) {
                vert.add(vert.direction);
            });
            effectPass.uniforms.brightness.value = -0.2 * flash;
            flash = Math.max(0, flash - 0.1);
            scene.rotation.y += passed * 0.1;
            camera.position.z += passed;
            camera.position.y += passed * 5;
            camera.lookAt(particleSystem.position);
            particleSystem.material.size = Math.max(0, particleSystem.material.size - passed * 0.3);

            var colorPos = Math.min(1, timer.getTime(time) * 0.14);
            particleSystem.material.color.setRGB(
                Math.max(0, fromColor.r - colorPos) + Math.max(0, toColor.r - (1 - colorPos)),
                Math.max(0, fromColor.g - colorPos) + Math.max(0, toColor.g - (1 - colorPos)),
                Math.max(0, fromColor.b - colorPos) + Math.max(0, toColor.b - (1 - colorPos))
            );

        },
        init: function(){
            effectBloom.copyUniforms.opacity.value = 3;
            effectPass.uniforms.aberration.value = 0.001;
        }

    };

    function createParticleSystem() {
        var particleMat = new THREE.ParticleSystemMaterial({
            color: 0xFFFFFF,
            size: 2,
            map: sparkTexture,
            transparent: true,
            depthWrite: false
        });
        particleMat.color.setRGB(3, 3, 3);

        var particleGeo = _.reduce(_.range(0, 5000), function (geo, idx) {
            var vertex = new THREE.Vector3();

            if(idx < 2000){
                vertex.direction = new THREE.Vector3(Math.random() - 0.5, 0, Math.random() - 0.5)
                    .normalize()
                    .multiplyScalar(particleSpeed * 4 + (Math.random() * 0.5));
            } else {
                vertex.direction = new THREE.Vector3(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5)
                    .normalize()
                    .multiplyScalar(particleSpeed + (Math.random() * 0.1));
            }

            geo.vertices.push(vertex);
            return geo;
        }, new THREE.Geometry());
        var particleSystem = new THREE.ParticleSystem(particleGeo, particleMat);
        particleSystem.sortParticles = true;
        return particleSystem;
    }
});<commit_msg>Add fadeout in enemy explosion scene.<commit_after>define(function(require){
    var fromColor = new THREE.Color(0xffb400);
    var toColor = new THREE.Color(0x51c8ff);
    var Ease = require("ease");

    var scene = new THREE.Object3D;
    var camera = new THREE.PerspectiveCamera(65, 16 / 9, 0.1, 5000);
    var Timer = require("Timer");
    var particleSpeed = 0.05;

    var StarField = require("component/starfield");
    scene.add(StarField.create(33));

    var sparkTexture = THREE.ImageUtils.loadTexture("images/spark.png");

    var particleSystem = createParticleSystem();
    scene.add(particleSystem);

    camera.position.set(0, 10, 30);
    camera.lookAt(particleSystem.position);

    var timer = new Timer();
    var flash = 1;
    var fadeOut = 0;
    return{
        scene: scene,
        camera: camera,
        render: function(time){
            var passed = timer.getPassed(time);
            _.each(particleSystem.geometry.vertices, function(vert) {
                vert.add(vert.direction);
            });
            flash = Math.max(0, flash - 0.1);
            scene.rotation.y += passed * 0.1;
            camera.position.z += passed;
            camera.position.y += passed * 5;
            camera.lookAt(particleSystem.position);
            particleSystem.material.size = Math.max(0, particleSystem.material.size - passed * 0.3);

            var colorPos = Math.min(1, timer.getTime(time) * 0.14);
            particleSystem.material.color.setRGB(
                Math.max(0, fromColor.r - colorPos) + Math.max(0, toColor.r - (1 - colorPos)),
                Math.max(0, fromColor.g - colorPos) + Math.max(0, toColor.g - (1 - colorPos)),
                Math.max(0, fromColor.b - colorPos) + Math.max(0, toColor.b - (1 - colorPos))
            );

            if(timer.getTime(time) > 4.5){
                effectPass.uniforms.brightness.value = -0.2 * flash - Ease.outCubic(fadeOut);
                fadeOut = Math.min(1, fadeOut + (passed * 0.15))
            } else {
                effectPass.uniforms.brightness.value = -0.2 * flash;
            }

        },
        init: function(){
            effectBloom.copyUniforms.opacity.value = 3;
            effectPass.uniforms.aberration.value = 0.001;
        }

    };

    function createParticleSystem() {
        var particleMat = new THREE.ParticleSystemMaterial({
            color: 0xFFFFFF,
            size: 2,
            map: sparkTexture,
            transparent: true,
            depthWrite: false
        });
        particleMat.color.setRGB(3, 3, 3);

        var particleGeo = _.reduce(_.range(0, 5000), function (geo, idx) {
            var vertex = new THREE.Vector3();

            if(idx < 2000){
                vertex.direction = new THREE.Vector3(Math.random() - 0.5, 0, Math.random() - 0.5)
                    .normalize()
                    .multiplyScalar(particleSpeed * 4 + (Math.random() * 0.5));
            } else {
                vertex.direction = new THREE.Vector3(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5)
                    .normalize()
                    .multiplyScalar(particleSpeed + (Math.random() * 0.1));
            }

            geo.vertices.push(vertex);
            return geo;
        }, new THREE.Geometry());
        var particleSystem = new THREE.ParticleSystem(particleGeo, particleMat);
        particleSystem.sortParticles = true;
        return particleSystem;
    }
});<|endoftext|>


<commit_before>var eventName = typeof(Turbolinks) !== 'undefined' ? 'turbolinks:load' : 'DOMContentLoaded';

if (!document.documentElement.hasAttribute("data-turbolinks-preview")) {
  document.addEventListener(eventName, function flash() {
    var flashData = JSON.parse(document.getElementById('shopify-app-flash').dataset.flash);

    var Toast = window['app-bridge'].actions.Toast;

    if (flashData.notice) {
      Toast.create(app, {
        message: flashData.notice,
        duration: 5000,
      }).dispatch(Toast.Action.SHOW);
    }

    if (flashData.error) {
      Toast.create(app, {
        message: flashData.error,
        duration: 5000,
        isError: true,
      }).dispatch(Toast.Action.SHOW);
    }

    document.removeEventListener(eventName, flash)
  });
}
<commit_msg>show flash when navigating with turbolinks<commit_after>var eventName = typeof(Turbolinks) !== 'undefined' ? 'turbolinks:load' : 'DOMContentLoaded';

if (!document.documentElement.hasAttribute("data-turbolinks-preview")) {
  document.addEventListener(eventName, function flash() {
    var flashData = JSON.parse(document.getElementById('shopify-app-flash').dataset.flash);

    var Toast = window['app-bridge'].actions.Toast;

    if (flashData.notice) {
      Toast.create(app, {
        message: flashData.notice,
        duration: 5000,
      }).dispatch(Toast.Action.SHOW);
    }

    if (flashData.error) {
      Toast.create(app, {
        message: flashData.error,
        duration: 5000,
        isError: true,
      }).dispatch(Toast.Action.SHOW);
    }
  });
}
<|endoftext|>


<commit_before>'use strict';
import React from 'react';
import Socket from 'socket.io-client';
import Reflux from 'reflux';

const socket = Socket.connect();

const actions = Reflux.createActions(
  ['textfieldUpdated']
);

let timer = null;

const dummyData = [{
  label: 'Title',
  data: [
    {
      text: 'Test Hest',
      img: 'http://dummyimage.com/50x50/000/fff'
    },
    {
      text: 'Hest Hest',
      img: 'http://dummyimage.com/50x50/000/fff'
    },
    {
      text: 'Fest Hest',
      img: 'http://dummyimage.com/50x50/000/fff'
    },
    {
      text: 'Gæst Hest',
      img: 'http://dummyimage.com/50x50/000/fff'
    }
  ]
},
  {
    label: 'Author',
    data: [
      {
        text: 'Test Hest',
        img: 'http://dummyimage.com/50x50/000/fff'
      },
      {
        text: 'Hest Hest',
        img: ''
      },
      {
        text: 'Fest Hest',
        img: ''
      },
      {
        text: 'Gæst Hest',
        img: ''
      }
    ]
  }];

const store = Reflux.createStore({
  listenables: [actions],

  _store: {
    data: []
  },

  init() {
    socket.on('getPopSuggestionsResponse', this.serviceResponse);
  },

  serviceResponse(data) {
    let _data = null;
    if (data.error) {
      console.error('PopSuggest responded with an error: ', data); // eslint-disable-line
      _data = [];
    }
    else {  // eslint-disable-line
      _data = dummyData;
    }

    this._store.data = _data;
    this.trigger(this._store);
  },

  onTextfieldUpdated(value) {
    socket.emit('getPopSuggestionsRequest', value);
  },

  getInitialState() {
    return this._store;
  }
});

var SearchField = React.createClass({
  mixins: [Reflux.connect(store)],

  render() {
    const AutoComplete = this.props.autocomplete;
    const text = this.state.text || '';
    const data = this.state.data || [];
    const autoCompleteVisible = (data.length >= 1 && text.length >= 1);

    return (

        <input type='text' placeholder='Søg og du skal finde' value={text} onChange={this._handleOnChange} onKeyUp={this._handleOnKeyUp} className={'search-input'}/>
        <AutoComplete data={data} visible={autoCompleteVisible}/>

    );
  },

  _handleOnChange(e) {
    const txt = e.target.value;
    this.setState({text: txt});
  },

  _handleOnKeyUp() {
    clearTimeout(timer);

    timer = setTimeout(() => {
      actions.textfieldUpdated(this.state.text);
    }, 250);
  },

  propTypes: {
    autocomplete: React.PropTypes.func.isRequired
  }
});

export default SearchField;
<commit_msg>handling data (should probably be moved to transform)<commit_after>'use strict';
import React from 'react';
import Socket from 'socket.io-client';
import Reflux from 'reflux';
import {isEmpty, sortBy} from 'lodash';

const socket = Socket.connect();

const actions = Reflux.createActions(
  ['textfieldUpdated']
);

const store = Reflux.createStore({
  listenables: [actions],

  _store: {
    data: {}
  },

  init() {
    socket.on('getPopSuggestionsResponse', this.serviceResponse);
  },

  serviceResponse(response) {
    let data = this._store.data;
    if (response.error) {
      console.error('PopSuggest responded with an error: ', response);
    }
    else if (response.isEmpty) {
      delete data[response.index];
    }
    else {
      data = this._parseResponse(response, data);
    }

    this._store.data = data;
    this.trigger(this._store);
  },

  _parseResponse(response, data) {
    const index = response.index;
    data[index] = {};

    switch (index) {
      case 'term.creator':
        let creators = this._getCreator(response);
        if (creators.length >= 1) {
          data[index].label = 'Forfatter';
          data[index].data = creators;
          data[index].weight = 1;
        }
        break;
      case 'term.title':
        let titles = this._getTitles(response);
        if (titles.length >= 1) {
          data[index].label = 'Titel';
          data[index].data = titles;
          data[index].weight = 0;
        }
        break;
      default:
        break;
    }

    return data;
  },

  _getCreator: function(response) {
    let creators = [];
    let counter = 0;
    response.docs.forEach((value) => {
      if (value['display.creator'] && counter < 5) {
        creators.push({
          text: value['display.creator'].join()
        });
        counter++;
      }
    });

    return creators;
  },

  _getTitles: function(response) {
    let titles = [];
    let counter = 0;
    response.docs.forEach((value) => {
      if (value['display.title'] && counter < 5) {
        titles.push({
          text: value['display.title'].join(),
          img: 'http://dummyimage.com/50x50/000/fff'
        });
        counter++;
      }
    });

    return titles;
  },

  onTextfieldUpdated(value) {
    if (value.length >= 1) {
      socket.emit('getPopSuggestionsRequest', value);
    }
    else {
      this._clearData();
    }
  },

  _clearData() {
    this._store.data = {};
    this.trigger(this._store);
  },

  getInitialState() {
    return this._store;
  }
});

var SearchField = React.createClass({
  mixins: [Reflux.connect(store)],
  timer: null,

  render() {
    const AutoComplete = this.props.autocomplete;
    const text = this.state.text || '';
    const data = this.state.data || {};
    const autoCompleteVisible = !isEmpty(data);

    return (

        <input type='text' placeholder='Søg og du skal finde' value={text} onChange={this._handleOnChange} onKeyUp={this._handleOnKeyUp} className={'search-input'}/>
        <AutoComplete data={data} visible={autoCompleteVisible}/>

    );
  },

  _handleOnChange(e) {
    const txt = e.target.value;
    this.setState({text: txt});
  },

  _handleOnKeyUp() {
    clearTimeout(this.timer);

    this.timer = setTimeout(() => {
      actions.textfieldUpdated(this.state.text);
    }, 150);
  },

  propTypes: {
    autocomplete: React.PropTypes.func.isRequired
  }
});

export default SearchField;
<|endoftext|>


<commit_before>/*
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import PropTypes from 'prop-types';
import sdk from '../../../index';
import dis from '../../../dispatcher';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';

// We match fairly liberally and leave it up to the server to reject if
// there are invalid characters etc.
const GROUP_REGEX = /^\+(.*?):(.*)$/;

export default React.createClass({
    displayName: 'CreateGroupDialog',
    propTypes: {
        onFinished: PropTypes.func.isRequired,
    },

    getInitialState: function() {
        return {
            groupName: '',
            groupId: '',
            groupError: null,
            creating: false,
            createError: null,
        };
    },

    _onGroupNameChange: function(e) {
        this.setState({
            groupName: e.target.value,
        });
    },

    _onGroupIdChange: function(e) {
        this.setState({
            groupId: e.target.value,
        });
    },

    _onGroupIdBlur: function(e) {
        this._checkGroupId();
    },

    _checkGroupId: function(e) {
        const parsedGroupId = this._parseGroupId(this.state.groupId);
        let error = null;
        if (parsedGroupId === null) {
            error = _t(
                "Community IDs must be of the form +localpart:%(domain)s",
                {domain: MatrixClientPeg.get().getDomain()},
            );
        } else {
            const groupId = parsedGroupId[0];
            const domain = parsedGroupId[1];

            if (!/^[a-zA-Z0-9]*$/.test(groupId)) {
                error = _t("Community IDs may only contain alphanumeric characters");
            } else  if (domain !== MatrixClientPeg.get().getDomain()) {
                error = _t(
                    "It is currently only possible to create communities on your own home server: "+
                    "use a community ID ending with %(domain)s",
                    {domain: MatrixClientPeg.get().getDomain()},
                );
            }
        }
        this.setState({
            groupIdError: error,
        });
        return error;
    },

    _onFormSubmit: function(e) {
        e.preventDefault();

        if (this._checkGroupId()) return;

        const parsedGroupId = this._parseGroupId(this.state.groupId);
        const profile = {};
        if (this.state.groupName !== '') {
            profile.name = this.state.groupName;
        }
        this.setState({creating: true});
        MatrixClientPeg.get().createGroup({
            localpart: parsedGroupId[0],
            profile: profile,
        }).then((result) => {
            dis.dispatch({
                action: 'view_group',
                group_id: result.group_id,
            });
            this.props.onFinished(true);
        }).catch((e) => {
            this.setState({createError: e});
        }).finally(() => {
            this.setState({creating: false});
        }).done();
    },

    _onCancel: function() {
        this.props.onFinished(false);
    },

    /**
     * Parse a string that may be a group ID
     * If the string is a valid group ID, return a list of [localpart, domain],
     * otherwise return null.
     *
     * @param {string} groupId The ID of the group
     * @return {string[]} array of localpart, domain
     */
    _parseGroupId: function(groupId) {
        const matches = GROUP_REGEX.exec(this.state.groupId);
        if (!matches || matches.length < 3) {
            return null;
        }
        return [matches[1], matches[2]];
    },

    render: function() {
        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
        const Spinner = sdk.getComponent('elements.Spinner');

        if (this.state.creating) {
            return <Spinner />;
        }

        let createErrorNode;
        if (this.state.createError) {
            // XXX: We should catch errcodes and give sensible i18ned messages for them,
            // rather than displaying what the server gives us, but synapse doesn't give
            // any yet.
            createErrorNode =

{ _t('Room creation failed') }

{ this.state.createError.message }

;
        }

        return (
            <BaseDialog className="mx_CreateGroupDialog" onFinished={this.props.onFinished}
                onEnterPressed={this._onFormSubmit}
                title={_t('Create Community')}
            >
                <form onSubmit={this._onFormSubmit}>

                                { _t('Community Name') }

                                <input id="groupname" className="mx_CreateGroupDialog_input"
                                    autoFocus={true} size="64"
                                    placeholder={_t('Example')}
                                    onChange={this._onGroupNameChange}
                                    value={this.state.groupName}
                                />

                                { _t('Community ID') }

                                <input id="groupid" className="mx_CreateGroupDialog_input"
                                    size="64"
                                    placeholder={_t('+example:%(domain)s', {domain: MatrixClientPeg.get().getDomain()})}
                                    onChange={this._onGroupIdChange}
                                    onBlur={this._onGroupIdBlur}
                                    value={this.state.groupId}
                                />

                            { this.state.groupIdError }

                        { createErrorNode }

                        <button onClick={this._onCancel}>
                            { _t("Cancel") }
                        </button>
                        <input type="submit" value={_t('Create')} className="mx_Dialog_primary" />

                </form>
            </BaseDialog>
        );
    },
});
<commit_msg>Space, man.<commit_after>/*
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import PropTypes from 'prop-types';
import sdk from '../../../index';
import dis from '../../../dispatcher';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';

// We match fairly liberally and leave it up to the server to reject if
// there are invalid characters etc.
const GROUP_REGEX = /^\+(.*?):(.*)$/;

export default React.createClass({
    displayName: 'CreateGroupDialog',
    propTypes: {
        onFinished: PropTypes.func.isRequired,
    },

    getInitialState: function() {
        return {
            groupName: '',
            groupId: '',
            groupError: null,
            creating: false,
            createError: null,
        };
    },

    _onGroupNameChange: function(e) {
        this.setState({
            groupName: e.target.value,
        });
    },

    _onGroupIdChange: function(e) {
        this.setState({
            groupId: e.target.value,
        });
    },

    _onGroupIdBlur: function(e) {
        this._checkGroupId();
    },

    _checkGroupId: function(e) {
        const parsedGroupId = this._parseGroupId(this.state.groupId);
        let error = null;
        if (parsedGroupId === null) {
            error = _t(
                "Community IDs must be of the form +localpart:%(domain)s",
                {domain: MatrixClientPeg.get().getDomain()},
            );
        } else {
            const groupId = parsedGroupId[0];
            const domain = parsedGroupId[1];

            if (!/^[a-zA-Z0-9]*$/.test(groupId)) {
                error = _t("Community IDs may only contain alphanumeric characters");
            } else if (domain !== MatrixClientPeg.get().getDomain()) {
                error = _t(
                    "It is currently only possible to create communities on your own home server: "+
                    "use a community ID ending with %(domain)s",
                    {domain: MatrixClientPeg.get().getDomain()},
                );
            }
        }
        this.setState({
            groupIdError: error,
        });
        return error;
    },

    _onFormSubmit: function(e) {
        e.preventDefault();

        if (this._checkGroupId()) return;

        const parsedGroupId = this._parseGroupId(this.state.groupId);
        const profile = {};
        if (this.state.groupName !== '') {
            profile.name = this.state.groupName;
        }
        this.setState({creating: true});
        MatrixClientPeg.get().createGroup({
            localpart: parsedGroupId[0],
            profile: profile,
        }).then((result) => {
            dis.dispatch({
                action: 'view_group',
                group_id: result.group_id,
            });
            this.props.onFinished(true);
        }).catch((e) => {
            this.setState({createError: e});
        }).finally(() => {
            this.setState({creating: false});
        }).done();
    },

    _onCancel: function() {
        this.props.onFinished(false);
    },

    /**
     * Parse a string that may be a group ID
     * If the string is a valid group ID, return a list of [localpart, domain],
     * otherwise return null.
     *
     * @param {string} groupId The ID of the group
     * @return {string[]} array of localpart, domain
     */
    _parseGroupId: function(groupId) {
        const matches = GROUP_REGEX.exec(this.state.groupId);
        if (!matches || matches.length < 3) {
            return null;
        }
        return [matches[1], matches[2]];
    },

    render: function() {
        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
        const Spinner = sdk.getComponent('elements.Spinner');

        if (this.state.creating) {
            return <Spinner />;
        }

        let createErrorNode;
        if (this.state.createError) {
            // XXX: We should catch errcodes and give sensible i18ned messages for them,
            // rather than displaying what the server gives us, but synapse doesn't give
            // any yet.
            createErrorNode =

{ _t('Room creation failed') }

{ this.state.createError.message }

;
        }

        return (
            <BaseDialog className="mx_CreateGroupDialog" onFinished={this.props.onFinished}
                onEnterPressed={this._onFormSubmit}
                title={_t('Create Community')}
            >
                <form onSubmit={this._onFormSubmit}>

                                { _t('Community Name') }

                                <input id="groupname" className="mx_CreateGroupDialog_input"
                                    autoFocus={true} size="64"
                                    placeholder={_t('Example')}
                                    onChange={this._onGroupNameChange}
                                    value={this.state.groupName}
                                />

                                { _t('Community ID') }

                                <input id="groupid" className="mx_CreateGroupDialog_input"
                                    size="64"
                                    placeholder={_t('+example:%(domain)s', {domain: MatrixClientPeg.get().getDomain()})}
                                    onChange={this._onGroupIdChange}
                                    onBlur={this._onGroupIdBlur}
                                    value={this.state.groupId}
                                />

                            { this.state.groupIdError }

                        { createErrorNode }

                        <button onClick={this._onCancel}>
                            { _t("Cancel") }
                        </button>
                        <input type="submit" value={_t('Create')} className="mx_Dialog_primary" />

                </form>
            </BaseDialog>
        );
    },
});
<|endoftext|>


<commit_before>'use strict';

var through2 = require('through2'),
	gutil = require('gulp-util'),
	mu = require('mu2'),
	path = require('path'),
	fs = require('fs'),
	_ = require('lodash');

module.exports = function(view, options) {
	options = options || {};

	var viewError = null;

	var parse = function(filename) {
		var js = fs.readFileSync(filename, 'utf8');
		return eval('(' + js + ')');
	}

	if (typeof view === 'string') {
		try {
			view = parse(view);
		} catch (e) {
			viewError = e;
		}
	}

	return through2.obj(function(file, enc, callback) {
		if (file.isNull()) {
			this.push(file);
			return callback();
		}

		if (file.isStream()) {
			this.emit('error', new gutil.PluginError('gulp-mu2', 'Streaming not supported'));
		}

		if (viewError) {
			this.emit('error', new gutil.PluginError('glup-mu2', viewError.toString()));
		}
		var page = path.basename(file.path, '.html');
		var data = {};
		data['pg-'+page] = true;
		data = _.extend(data, view);
		try {
			var datafile = gutil.replaceExtension(file.path, '.json');
			if (fs.existsSync(datafile)) {
				data = _.extend(data, parse(datafile));
			}
		} catch (e) {
			console.log(e.toString());
		}

		if (options.root) {
			mu.root = options.root;
		} else {
			mu.root = file.base;
		}

		var stream = this;
		mu.compileText(file.path, file.contents.toString('utf8'), function(err, parsed) {
			if (parsed) {
				var html = '';
				var i = 0;
				(function next(err) {
					if (err) {
						stream.push(file);
						return callback();
					}
					if (i < parsed.partials.length) {
						mu.compile(parsed.partials[i], next);
						i++;
					} else {
						mu.render(parsed, data)
						.on('data', function (chunk) {
							html += chunk;
						})
						.on('end', function() {
							file.contents = new Buffer(html);
                            if (typeof options.extension === 'string') {
                                file.path = gutil.replaceExtension(file.path, options.extension);
                            }
							stream.push(file);
							callback();
						});
					}
				}());
			}
		});
	});
};

<commit_msg>fix: fall back to eval if JSON.parse fails<commit_after>'use strict';

var through2 = require('through2'),
	gutil = require('gulp-util'),
	mu = require('mu2'),
	path = require('path'),
	fs = require('fs'),
	_ = require('lodash');

module.exports = function(view, options) {
	options = options || {};

	var viewError = null;

	var parse = function(filename) {
		var js = fs.readFileSync(filename, 'utf8');
		return eval('(' + js + ')');
	}

	if (typeof view === 'string') {
		try {
			view = parse(view);
		} catch (e) {
			view = eval('(' + fs.readFileSync(view, 'utf8')) + ')');
		}
	}

	return through2.obj(function(file, enc, callback) {
		if (file.isNull()) {
			this.push(file);
			return callback();
		}

		if (file.isStream()) {
			this.emit('error', new gutil.PluginError('gulp-mu2', 'Streaming not supported'));
		}

		if (viewError) {
			this.emit('error', new gutil.PluginError('glup-mu2', viewError.toString()));
		}
		var page = path.basename(file.path, '.html');
		var data = {};
		data['pg-'+page] = true;
		data = _.extend(data, view);
		try {
			var datafile = gutil.replaceExtension(file.path, '.json');
			if (fs.existsSync(datafile)) {
				data = _.extend(data, parse(datafile));
			}
		} catch (e) {
			console.log(e.toString());
		}

		if (options.root) {
			mu.root = options.root;
		} else {
			mu.root = file.base;
		}

		var stream = this;
		mu.compileText(file.path, file.contents.toString('utf8'), function(err, parsed) {
			if (parsed) {
				var html = '';
				var i = 0;
				(function next(err) {
					if (err) {
						stream.push(file);
						return callback();
					}
					if (i < parsed.partials.length) {
						mu.compile(parsed.partials[i], next);
						i++;
					} else {
						mu.render(parsed, data)
						.on('data', function (chunk) {
							html += chunk;
						})
						.on('end', function() {
							file.contents = new Buffer(html);
                            if (typeof options.extension === 'string') {
                                file.path = gutil.replaceExtension(file.path, options.extension);
                            }
							stream.push(file);
							callback();
						});
					}
				}());
			}
		});
	});
};

<|endoftext|>