<commit_before>import 'isomorphic-fetch';
import _ from 'lodash';
import Promise from 'bluebird';

/**
 * Dataset service
 * @example:
    import DatasetService from '..path';
    const ds = new DatasetService('42de3f98-ba1c-4572-a227-2e18d45239a5', {
      apiURL: 'https://api.resourcewatch.org/v1'
    });
    ds.getFilters().then((data) => {
      console.log(data)
    });
 */
export default class DatasetService {

  constructor(datasetId, options) {
    if (!options) {
      throw new Error('options params is required.');
    }
    if (!options.apiURL || options.apiURL === '') {
      throw new Error('options.apiURL param is required.');
    }
    this.datasetId = datasetId;
    this.opts = options;
  }

  /**
   * Get dataset info
   * @returns {Promise}
   */
  fetchData(includes = '') {
    return fetch(`${this.opts.apiURL}/dataset/${this.datasetId}?includes=${includes}`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  /**
   * Get filtered data
   * @returns {Promise}
   */
  fetchFilteredData(query) {
    return fetch(`${this.opts.apiURL}/query/${this.datasetId}?sql=${query}`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  /**
   * Get Jiminy chart suggestions
   * @returns {Promise}
   */
  fetchJiminy(query) {
    return fetch(`${this.opts.apiURL}/jiminy`, {
      method: 'POST',
      body: JSON.stringify({ sql: query }),
      headers: {
        "Content-Type": "application/json"
      }
    })
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  /**
   *  Get max and min or values depending on field type
   *  @returns {Promise}
   */
  getFilter(fieldData) {
    return new Promise((resolve) => {
      if (fieldData.columnType === 'number' || fieldData.columnType === 'date') {
        this.getMinAndMax(fieldData.columnName, fieldData.tableName).then((data) => {
          fieldData.properties = data;
          resolve(fieldData);
        });
      } else {
        this.getValues(fieldData.columnName, fieldData.tableName).then((data) => {
          fieldData.properties = data;
          resolve(fieldData);
        });
      }
    });
  }

  getFilters() {
    return new Promise((resolve) => {
      this.getFields().then((fieldsData) => {
        const filteredFields = fieldsData.fields.filter(field => field.columnType === 'number' || field.columnType === 'date' || field.columnType === 'string');
        const promises = _.map(filteredFields, (field) => {
          if (field.columnType === 'number' || field.columnType === 'date') {
            return this.getMinAndMax(field.columnName, fieldsData.tableName);
          }
          return this.getValues(field.columnName, fieldsData.tableName);
        });
        Promise.all(promises).then((results) => {
          const filters = _.map(filteredFields, (field, index) => {
            const filterResult = {
              columnName: field.columnName,
              columnType: field.columnType
            };
            if (field.columnType === 'number' || field.columnType === 'date') {
              filterResult.properties = results[index];
            } else {
              filterResult.properties = {
                values: results[index]
              };
            }
            return filterResult;
          });
          resolve(filters);
        });
      });
    });
  }

  getFields() {
    return fetch(`${this.opts.apiURL}/fields/${this.datasetId}`)
      .then(response => response.json())
      .then((jsonData) => {
        const parsedData = {
          tableName: jsonData.tableName,
          fields: _.map(jsonData.fields, (value, key) => ({
            columnName: key,
            columnType: value.type
          }))
        };
        return parsedData;
      });
  }

  getMinAndMax(columnName, tableName) {
    if (!this.tableName && !tableName) {
      throw Error('tableName was not specified.');
    }
    const table = tableName || this.tableName;
    const query = `SELECT Min(${columnName}) AS min, Max(${columnName}) AS max FROM ${table}`;
    return new Promise((resolve) => {
      // TODO: remove cache param
      fetch(`https://api.resourcewatch.org/v1/query/${this.datasetId}?sql=${query}`)
        .then(response => response.json())
        .then((jsonData) => {
          if (jsonData.data) {
            resolve(jsonData.data[0]);
          } else {
            resolve({});
          }
        });
    });
  }

  getValues(columnName, tableName, uniqs = true) {
    if (!this.tableName && !tableName) {
      throw Error('tableName was not specified.');
    }
    const table = tableName || this.tableName;
    const uniqQueryPart = uniqs ? `GROUP BY ${columnName}` : '';
    const query = `SELECT ${columnName} FROM ${table} ${uniqQueryPart} ORDER BY ${columnName}`;
    return new Promise((resolve) => {
      // TODO: remove cache param
      fetch(`https://api.resourcewatch.org/v1/query/${this.datasetId}?sql=${query}`)
        .then(response => response.json())
        .then((jsonData) => {
          const parsedData = _.map(jsonData.data, data => data[columnName]);
          resolve(parsedData);
        });
    });
  }

  getLayers() {
    return fetch(`${this.opts.apiURL}/dataset/${this.datasetId}/layer?app=rw`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  getDownloadURI(tableName, datasetName) {
    // emulates trigger of download creating a link in memory and clicking on it
    const a = document.createElement('a');
    a.href = `${this.opts.apiURL}/download/${this.datasetId}?sql=SELECT * FROM ${tableName}`;
    a.style.display = 'none';
    a.download = datasetName;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  }

  getSimilarDatasets(tags) {
    return fetch(`${this.opts.apiURL}/dataset/vocabulary/find?legacy=${tags}`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  getDatasets(datasetIDs) {
    return fetch(`${this.opts.apiURL}/dataset/?ids=${datasetIDs}&includes=widget,layer`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }
}
<commit_msg>adding filter by app in dataset service<commit_after>import 'isomorphic-fetch';
import _ from 'lodash';
import Promise from 'bluebird';

/**
 * Dataset service
 * @example:
    import DatasetService from '..path';
    const ds = new DatasetService('42de3f98-ba1c-4572-a227-2e18d45239a5', {
      apiURL: 'https://api.resourcewatch.org/v1'
    });
    ds.getFilters().then((data) => {
      console.log(data)
    });
 */
export default class DatasetService {

  constructor(datasetId, options) {
    if (!options) {
      throw new Error('options params is required.');
    }
    if (!options.apiURL || options.apiURL === '') {
      throw new Error('options.apiURL param is required.');
    }
    this.datasetId = datasetId;
    this.opts = options;
  }

  /**
   * Get dataset info
   * @returns {Promise}
   */
  fetchData(includes = '', applications = [process.env.APPLICATIONS]) {
    return fetch(`${this.opts.apiURL}/dataset/${this.datasetId}?application=${applications.join(',')}&includes=${includes}`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  /**
   * Get filtered data
   * @returns {Promise}
   */
  fetchFilteredData(query) {
    return fetch(`${this.opts.apiURL}/query/${this.datasetId}?sql=${query}`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  /**
   * Get Jiminy chart suggestions
   * @returns {Promise}
   */
  fetchJiminy(query) {
    return fetch(`${this.opts.apiURL}/jiminy`, {
      method: 'POST',
      body: JSON.stringify({ sql: query }),
      headers: {
        "Content-Type": "application/json"
      }
    })
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  /**
   *  Get max and min or values depending on field type
   *  @returns {Promise}
   */
  getFilter(fieldData) {
    return new Promise((resolve) => {
      if (fieldData.columnType === 'number' || fieldData.columnType === 'date') {
        this.getMinAndMax(fieldData.columnName, fieldData.tableName).then((data) => {
          fieldData.properties = data;
          resolve(fieldData);
        });
      } else {
        this.getValues(fieldData.columnName, fieldData.tableName).then((data) => {
          fieldData.properties = data;
          resolve(fieldData);
        });
      }
    });
  }

  getFilters() {
    return new Promise((resolve) => {
      this.getFields().then((fieldsData) => {
        const filteredFields = fieldsData.fields.filter(field => field.columnType === 'number' || field.columnType === 'date' || field.columnType === 'string');
        const promises = _.map(filteredFields, (field) => {
          if (field.columnType === 'number' || field.columnType === 'date') {
            return this.getMinAndMax(field.columnName, fieldsData.tableName);
          }
          return this.getValues(field.columnName, fieldsData.tableName);
        });
        Promise.all(promises).then((results) => {
          const filters = _.map(filteredFields, (field, index) => {
            const filterResult = {
              columnName: field.columnName,
              columnType: field.columnType
            };
            if (field.columnType === 'number' || field.columnType === 'date') {
              filterResult.properties = results[index];
            } else {
              filterResult.properties = {
                values: results[index]
              };
            }
            return filterResult;
          });
          resolve(filters);
        });
      });
    });
  }

  getFields() {
    return fetch(`${this.opts.apiURL}/fields/${this.datasetId}`)
      .then(response => response.json())
      .then((jsonData) => {
        const parsedData = {
          tableName: jsonData.tableName,
          fields: _.map(jsonData.fields, (value, key) => ({
            columnName: key,
            columnType: value.type
          }))
        };
        return parsedData;
      });
  }

  getMinAndMax(columnName, tableName) {
    if (!this.tableName && !tableName) {
      throw Error('tableName was not specified.');
    }
    const table = tableName || this.tableName;
    const query = `SELECT Min(${columnName}) AS min, Max(${columnName}) AS max FROM ${table}`;
    return new Promise((resolve) => {
      // TODO: remove cache param
      fetch(`https://api.resourcewatch.org/v1/query/${this.datasetId}?sql=${query}`)
        .then(response => response.json())
        .then((jsonData) => {
          if (jsonData.data) {
            resolve(jsonData.data[0]);
          } else {
            resolve({});
          }
        });
    });
  }

  getValues(columnName, tableName, uniqs = true) {
    if (!this.tableName && !tableName) {
      throw Error('tableName was not specified.');
    }
    const table = tableName || this.tableName;
    const uniqQueryPart = uniqs ? `GROUP BY ${columnName}` : '';
    const query = `SELECT ${columnName} FROM ${table} ${uniqQueryPart} ORDER BY ${columnName}`;
    return new Promise((resolve) => {
      // TODO: remove cache param
      fetch(`https://api.resourcewatch.org/v1/query/${this.datasetId}?sql=${query}`)
        .then(response => response.json())
        .then((jsonData) => {
          const parsedData = _.map(jsonData.data, data => data[columnName]);
          resolve(parsedData);
        });
    });
  }

  getLayers() {
    return fetch(`${this.opts.apiURL}/dataset/${this.datasetId}/layer?app=rw`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  getDownloadURI(tableName, datasetName) {
    // emulates trigger of download creating a link in memory and clicking on it
    const a = document.createElement('a');
    a.href = `${this.opts.apiURL}/download/${this.datasetId}?sql=SELECT * FROM ${tableName}`;
    a.style.display = 'none';
    a.download = datasetName;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  }

  getSimilarDatasets(tags) {
    return fetch(`${this.opts.apiURL}/dataset/vocabulary/find?legacy=${tags}`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }

  getDatasets(datasetIDs) {
    return fetch(`${this.opts.apiURL}/dataset/?ids=${datasetIDs}&includes=widget,layer`)
      .then(response => response.json())
      .then(jsonData => jsonData.data);
  }
}
<|endoftext|>


<commit_before>angular.module('modifyfeedback', [])
.directive('forward', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).hover(function(e) {
                $(this).siblings('.the-modify-categories-menu').css({'display' : 'block'}).hover(function() {}, function() {
                    $(this).hide();
                })
            });
        }
    }
})
.directive('saveFeedback', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                e.preventDefault();
            });
        }
    }
})
.directive('toggle', function(FeedbackControlService) {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var class_name = $(this).attr('class');

                if(class_name == "blue-bar-feature") {
                    $(this).css({
                       'background-color': '#e7edf2'
                     , '-webkit-border-radius': '10px'
                     , '-moz-border-radius': '10px'
                     , 'border-radius': '10px'
                    });
                    $(".blue-bar-publish").removeAttr('style');
                    $(".cat-picks").removeAttr('style');
                }

                if(class_name == "blue-bar-publish") {
                    $(this).css({
                       'background-color': '#e7edf2'
                     , '-webkit-border-radius': '10px'
                     , '-moz-border-radius': '10px'
                     , 'border-radius': '10px'
                    });
                    $(".blue-bar-feature").removeAttr('style');
                    $(".cat-picks").removeAttr('style');
                }

                if(class_name == "blue-bar-flag") {
                    var state = $(this).attr('state');
                    var feedid = $(this).attr('feedid');
                    var feed_status = $(this).attr('status');
                    var current_cat_id = $(".category-box").attr('id');

                    if(state == 1) {
                        $(this).removeAttr('style');
                        $(this).attr('state', 0);
                    } else {
                        $(this).css({
                           'background-color': '#e7edf2'
                         , '-webkit-border-radius': '10px'
                         , '-moz-border-radius': '10px'
                         , 'border-radius': '10px'
                        });
                        $(this).attr('state', 1);
                    }

                    var state = $(this).attr('state') == true;
                    var data = {
                        id: feedid
                      , status: (state) ? feed_status : 'unflag'
                      , catid: current_cat_id
                    }

                    console.log(data);

                    //FeedbackControlService.change_status(data, true);
                }

                if(class_name == "blue-bar-delete") {
                    $(".blue-bar-feature, .blue-bar-publish, .blue-bar-flag, .cat-picks").removeAttr('style');
                }
                e.preventDefault();
            });
        }
    }
})
.directive('categoryPick', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {

                var deselect_this = false;

                $(this).parent().siblings().children('a').each(function() {
                    $(this).removeAttr("style");
                });

                if(!deselect_this) {
                    $(this).attr('style', "background: #cd5555");
                }

                $(".blue-bar-feature").removeAttr('style');
                $(".blue-bar-publish").removeAttr('style');
                e.preventDefault();
            });
        }
    }
})
<commit_msg>humming bird<commit_after>angular.module('modifyfeedback', [])
.directive('forward', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).hover(function(e) {
                $(this).siblings('.the-modify-categories-menu').css({'display' : 'block'}).hover(function() {}, function() {
                    $(this).hide();
                })
            });
        }
    }
})
.directive('saveFeedback', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                e.preventDefault();
            });
        }
    }
})
.directive('toggle', function(FeedbackControlService) {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var class_name = $(this).attr('class');

                if(class_name == "blue-bar-feature") {
                    $(this).css({
                       'background-color': '#e7edf2'
                     , '-webkit-border-radius': '10px'
                     , '-moz-border-radius': '10px'
                     , 'border-radius': '10px'
                    });
                    $(".blue-bar-publish").removeAttr('style');
                    $(".cat-picks").removeAttr('style');
                }

                if(class_name == "blue-bar-publish") {
                    $(this).css({
                       'background-color': '#e7edf2'
                     , '-webkit-border-radius': '10px'
                     , '-moz-border-radius': '10px'
                     , 'border-radius': '10px'
                    });
                    $(".blue-bar-feature").removeAttr('style');
                    $(".cat-picks").removeAttr('style');
                }

                if(class_name == "blue-bar-flag") {
                    var state = $(this).attr('state');
                    var feedid = $(this).attr('feedid');
                    var feed_status = $(this).attr('status');
                    var current_cat_id = $(".category-box").attr('id');

                    if(state == 1) {
                        $(this).removeAttr('style');
                        $(this).attr('state', 0);
                    } else {
                        $(this).css({
                           'background-color': '#e7edf2'
                         , '-webkit-border-radius': '10px'
                         , '-moz-border-radius': '10px'
                         , 'border-radius': '10px'
                        });
                        $(this).attr('state', 1);
                    }

                    var state = $(this).attr('state') == true;
                    var data = {
                        id: feedid
                      , status: (state) ? feed_status : 'unflag'
                      , catid: current_cat_id
                    }
                    FeedbackControlService.change_status(data, true);
                }

                if(class_name == "blue-bar-delete") {
                    $(".blue-bar-feature, .blue-bar-publish, .blue-bar-flag, .cat-picks").removeAttr('style');
                }
                e.preventDefault();
            });
        }
    }
})
.directive('categoryPick', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {

                var deselect_this = false;

                $(this).parent().siblings().children('a').each(function() {
                    $(this).removeAttr("style");
                });

                if(!deselect_this) {
                    $(this).attr('style', "background: #cd5555");
                }

                $(".blue-bar-feature").removeAttr('style');
                $(".blue-bar-publish").removeAttr('style');
                e.preventDefault();
            });
        }
    }
})
<|endoftext|>


<commit_before>/* eslint-env es6 */
/* global THREE */

(function() {
  'use strict';

  let container;

  let scene, camera, renderer;

  function dispose( mesh ) {
    if ( mesh instanceof THREE.Mesh ) {
      mesh.geometry.dispose();
    }
  }

  function init() {
    container = document.createElement( 'div' );
    document.body.appendChild( container );

    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    container.appendChild( renderer.domElement );

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight );
    camera.position.set( 0, 0, 8 );

    const controls = new THREE.OrbitControls( camera, renderer.domElement );
    controls.addEventListener( 'change', render );

    const axisHelper = new THREE.AxisHelper();
    scene.add( axisHelper );

    const gridHelper = new THREE.GridHelper( 4, 20 );
    gridHelper.position.y = -2;
    gridHelper.material.opacity = 0.5;
    gridHelper.material.transparent = true;
    scene.add( gridHelper );

    let group = new THREE.Group();
    scene.add( group );

    function onInput( event ) {
      try {
        group.traverse( dispose );
        scene.remove( group );

        const fn = new Function( [ 'THREE' ], event.target.value );

        group = new THREE.Group();
        group.add( ...fn( THREE ) );
        scene.add( group );

        render();

        if ( !event.target.validity.valid ) {
          console.info( '' );
        }

        event.target.setCustomValidity( '' );
      } catch ( error ) {
        console.error( error );
        event.target.setCustomValidity( 'Invalid function' );
      }
    }

    const textarea = document.getElementById( 'textarea-commands' );
    textarea.addEventListener( 'input', onInput );
  }

  function render() {
    renderer.render( scene, camera );
  }

  init();
  render();
}());
<commit_msg>repl: Persist state in location.search.<commit_after>/* eslint-env es6 */
/* global THREE */

(function() {
  'use strict';

  let container;

  let scene, camera, renderer;

  function dispose( mesh ) {
    if ( mesh instanceof THREE.Mesh ) {
      mesh.geometry.dispose();
    }
  }

  function init() {
    container = document.createElement( 'div' );
    document.body.appendChild( container );

    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    container.appendChild( renderer.domElement );

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight );
    camera.position.set( 0, 0, 8 );

    const controls = new THREE.OrbitControls( camera, renderer.domElement );
    controls.addEventListener( 'change', render );

    const axisHelper = new THREE.AxisHelper();
    scene.add( axisHelper );

    const gridHelper = new THREE.GridHelper( 4, 20 );
    gridHelper.position.y = -2;
    gridHelper.material.opacity = 0.5;
    gridHelper.material.transparent = true;
    scene.add( gridHelper );

    let group = new THREE.Group();
    scene.add( group );

    function onInput( event ) {
      try {
        group.traverse( dispose );
        scene.remove( group );

        const fn = new Function( [ 'THREE' ], event.target.value );

        group = new THREE.Group();
        group.add( ...fn( THREE ) );
        scene.add( group );

        render();

        const params = new URLSearchParams( window.location.search );
        params.set( 'commands', event.target.value.trim() );
        window.history.replaceState( '', '', `${ location.pathname }?${ params }` );

        if ( !event.target.validity.valid ) {
          console.info( '' );
        }

        event.target.setCustomValidity( '' );
      } catch ( error ) {
        console.error( error );
        event.target.setCustomValidity( 'Invalid function' );
      }
    }

    const textarea = document.getElementById( 'textarea-commands' );
    textarea.addEventListener( 'input', onInput );
    // Disable OrbitControls while textarea is focused.
    textarea.addEventListener( 'keydown', event => event.stopPropagation() );

    const params = new URLSearchParams( window.location.search )
    textarea.value = params.get( 'commands' );
    textarea.dispatchEvent( new Event( 'input' ) );
  }

  function render() {
    renderer.render( scene, camera );
  }

  init();
  render();
}());
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React from 'react'
import {SanityLogo as SanityLogotype} from '@sanity/logos'
import {Spinner, Container, Flex} from '@sanity/ui'
import {of} from 'rxjs'
import {map, catchError} from 'rxjs/operators'
import CookieTest from './CookieTest'
import ErrorDialog from './ErrorDialog'
import UnauthorizedUser from './UnauthorizedUser'
import {versionedClient} from './versionedClient'
import {userStore, LoginDialog} from './legacyParts'

const isProjectLogin = versionedClient.config().useProjectHostname
const projectId =
  isProjectLogin && versionedClient.config().projectId ? versionedClient.config().projectId : null

export default class LoginWrapper extends React.PureComponent {
  static propTypes = {
    children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired,
    title: PropTypes.node,
    description: PropTypes.node,
    sanityLogo: PropTypes.node,
    SanityLogo: PropTypes.func,
    LoadingScreen: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
  }

  static defaultProps = {
    title: 'Choose a login provider',
    description: null,
    sanityLogo: null,
    SanityLogo: SanityLogotype,
    LoadingScreen: (
      <Container padding={4} height="fill">
        <Flex justify="center" align="center" height="fill">
          <Spinner />
        </Flex>
      </Container>
    ),
  }

  state = {isLoading: true, user: null, error: null}

  userSubscription = null

  constructor(props) {
    super(props)

    let sync = true
    this.userSubscription = userStore.me
      .pipe(
        map((currentUser) => ({
          user: currentUser,
          isLoading: false,
        })),
        catchError((error) => of({user: null, error, isLoading: false}))
      )
      .subscribe({
        next: (userState) => {
          // Because observables _can_ be synchronous, it's not safe to call `setState` as it is a noop
          // We must therefore explicitly check whether or not we were call synchronously
          if (sync) {
            // eslint-disable-next-line react/no-direct-mutation-state
            this.state = {...this.state, ...userState}
          } else {
            this.setState(userState)
          }
        },
      })
    sync = false
  }

  componentWillUnmount() {
    if (this.userSubscription) {
      this.userSubscription.unsubscribe()
    }
  }

  handleRetry = () => {
    this.setState({error: null, isLoading: true})
    userStore.actions.retry()
  }

  render() {
    const {error, user, isLoading} = this.state
    const {children, LoadingScreen, sanityLogo, SanityLogo} = this.props
    if (sanityLogo) {
      const warning =
        'sanityLogo is a deprecated property on LoginWrapper. Pass a React component to the SanityLogo property instead.'
      console.warn(warning) // eslint-disable-line no-console
    }

    if (isLoading) {
      return typeof LoadingScreen === 'function' ? (
        <LoadingScreen center fullscreen />
      ) : (
        LoadingScreen
      )
    }

    if (error) {
      return <ErrorDialog onRetry={this.handleRetry} error={error} />
    }

    if (!user) {
      return (
        <CookieTest {...this.props}>
          <LoginDialog
            title={this.props.title}
            description={this.props.description}
            SanityLogo={SanityLogo}
            projectId={projectId}
          />
        </CookieTest>
      )
    }

    if (projectId && !user.role) {
      return <UnauthorizedUser user={user} />
    }

    return typeof children === 'function' ? children(user) : children
  }
}
<commit_msg>fix(default-login): fix react warnings<commit_after>import PropTypes from 'prop-types'
import React from 'react'
import {SanityLogo as SanityLogotype} from '@sanity/logos'
import {Spinner, Container, Flex} from '@sanity/ui'
import {of} from 'rxjs'
import {map, catchError} from 'rxjs/operators'
import CookieTest from './CookieTest'
import ErrorDialog from './ErrorDialog'
import UnauthorizedUser from './UnauthorizedUser'
import {versionedClient} from './versionedClient'
import {userStore, LoginDialog} from './legacyParts'

const isProjectLogin = versionedClient.config().useProjectHostname
const projectId =
  isProjectLogin && versionedClient.config().projectId ? versionedClient.config().projectId : null

export default class LoginWrapper extends React.PureComponent {
  static propTypes = {
    children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
    title: PropTypes.node,
    description: PropTypes.node,
    sanityLogo: PropTypes.node,
    SanityLogo: PropTypes.oneOfType([PropTypes.object, PropTypes.node, PropTypes.func]),
    LoadingScreen: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
  }

  static defaultProps = {
    title: 'Choose a login provider',
    description: null,
    sanityLogo: null,
    SanityLogo: SanityLogotype,
    LoadingScreen: (
      <Container padding={4} height="fill">
        <Flex justify="center" align="center" height="fill">
          <Spinner />
        </Flex>
      </Container>
    ),
  }

  state = {isLoading: true, user: null, error: null}

  userSubscription = null

  constructor(props) {
    super(props)

    let sync = true
    this.userSubscription = userStore.me
      .pipe(
        map((currentUser) => ({
          user: currentUser,
          isLoading: false,
        })),
        catchError((error) => of({user: null, error, isLoading: false}))
      )
      .subscribe({
        next: (userState) => {
          // Because observables _can_ be synchronous, it's not safe to call `setState` as it is a noop
          // We must therefore explicitly check whether or not we were call synchronously
          if (sync) {
            // eslint-disable-next-line react/no-direct-mutation-state
            this.state = {...this.state, ...userState}
          } else {
            this.setState(userState)
          }
        },
      })
    sync = false
  }

  componentWillUnmount() {
    if (this.userSubscription) {
      this.userSubscription.unsubscribe()
    }
  }

  handleRetry = () => {
    this.setState({error: null, isLoading: true})
    userStore.actions.retry()
  }

  render() {
    const {error, user, isLoading} = this.state
    const {children, LoadingScreen, sanityLogo, SanityLogo} = this.props
    if (sanityLogo) {
      const warning =
        'sanityLogo is a deprecated property on LoginWrapper. Pass a React component to the SanityLogo property instead.'
      console.warn(warning) // eslint-disable-line no-console
    }

    if (isLoading) {
      return typeof LoadingScreen === 'function' ? (
        <LoadingScreen center fullscreen />
      ) : (
        LoadingScreen
      )
    }

    if (error) {
      return <ErrorDialog onRetry={this.handleRetry} error={error} />
    }

    if (!user) {
      return (
        <CookieTest {...this.props}>
          <LoginDialog
            title={this.props.title}
            description={this.props.description}
            SanityLogo={SanityLogo}
            projectId={projectId}
          />
        </CookieTest>
      )
    }

    if (projectId && !user.role) {
      return <UnauthorizedUser user={user} />
    }

    return typeof children === 'function' ? children(user) : <>{children}</>
  }
}
<|endoftext|>


<commit_before>

function _key (o, key, value) {
	key.split('.').forEach(function (k, i, keys) {
		if( i === keys.length - 1 ) {
			o[k] = value;
		} else {
			o[k] = o[k] || {};
			o = o[k];
		}
	});
}

function toCamelCase (text) {
	return text.replace(/[_-](\w)/g, function (_matched, letter) {
		return letter.toUpperCase();
	});
}

function toUnderscoreCase (text) {
	return text.replace(/-(\w)/g, function (_matched, letter) {
		return '_' + letter;
	}).replace(/([a-z])([A-Z])/g, function (_matched, a, b) {
		return a + '_' + b;
	}).toLowerCase();
}

function deserialize (querystring, decode) {

	var result = {};

  if( !querystring.trim() ) return;

	querystring.split('&').forEach(function (keyValue) {
		var matched = keyValue.match(/(.*?)=(.*)/);

		if( !matched ) {
			throw new Error('could not parse ' + keyValue);
		}

		_key(result, toUnderscoreCase(matched[1]), decode ? decodeURI(matched[2]) : matched[2] );

	});

	return result;
}

module.exports = {
  deserialize: deserialize,
  toUnderscoreCase: toUnderscoreCase,
  toCamelCase: toCamelCase,
};
<commit_msg>fixed deserialize issue<commit_after>

function _key (o, key, value) {
	key.split('.').forEach(function (k, i, keys) {
		if( i === keys.length - 1 ) {
			o[k] = value;
		} else {
			o[k] = o[k] || {};
			o = o[k];
		}
	});
}

function toCamelCase (text) {
	return text.replace(/[_-](\w)/g, function (_matched, letter) {
		return letter.toUpperCase();
	});
}

function toUnderscoreCase (text) {
	return text.replace(/-(\w)/g, function (_matched, letter) {
		return '_' + letter;
	}).replace(/([a-z])([A-Z])/g, function (_matched, a, b) {
		return a + '_' + b;
	}).toLowerCase();
}

function deserialize (querystring, decode, throw_errors) {

	var result = {};

	querystring.split('&').forEach(function (keyValue) {
		var matched = keyValue.match(/(.*?)=(.*)/);

		if( !matched ) {
      if( !throw_errors ) return;
			throw new Error('could not parse ' + keyValue);
		}

		_key(result, toUnderscoreCase(matched[1]), decode ? decodeURI(matched[2]) : matched[2] );

	});

	return result;
}

module.exports = {
  deserialize: deserialize,
  toUnderscoreCase: toUnderscoreCase,
  toCamelCase: toCamelCase,
};
<|endoftext|>


<commit_before>function Sonic() {

    // Position de l'animation courante parmi les frames
    this.currentAnimationFrame = 0;

    // Taille en pixels d'une frame d'animation
    this.animationFrameWidth = 44;

    // Nombre de frames dans les animations
    this.standAnimationNumberFrame = 1;
    this.runAnimationNumberFrame = 8;
    this.dashAnimationNumberFrame = 4;
    this.ballAnimationNumberFrame = 5;
    this.stopAnimationNumberFrame = 3;

    // Position y de l'animation courante dans le sprite général.
    this.animationY = 0;

    // Sert à controler la boucle d'animation
    this.animationLoop;

    this.currentState = this.STANDING;
}

Sonic.prototype.STANDING = 'STANDING';
Sonic.prototype.RUNNING = 'RUNNING';
Sonic.prototype.DASHING = 'DASHING';
Sonic.prototype.JUMPING = 'JUMPING';

// Affichage de sonic dans un contexte de canvas
Sonic.prototype.draw = function (context, x, y) {

    var endLevel = level.nbTotalTilesX * level.tileSize;
    var halfScreen = level.tilesDisplayX / 2 * level.tileSize;
    var displayX = x;

    if (level.isAtEndOfLevel(x)) { // Fin de niveau
        displayX = x - endLevel + halfScreen * 2;
    } else if (level.isAtMiddleOfLevel(x)) { // Milieu de niveau
        displayX = halfScreen;
    }

    context.drawImage(resources.images['sonicSprites'], this.currentAnimationFrame * this.animationFrameWidth, this.animationY, 44, 46, displayX - 22, y - 30, 44, 46);
};

// Efface l'animation courante
Sonic.prototype.clearCurrentAnimation = function () {
    this.currentAnimationFrame = 0;
    clearTimeout(this.animationLoop);
};

Sonic.prototype.standLeft = function () {
    if (this.currentState != this.STANDING) {
        this.clearCurrentAnimation();
        this.animationY = 0;
        this.currentState = this.STANDING;
    }
};

Sonic.prototype.standRight = function () {
    if (this.currentState != this.STANDING) {
        this.clearCurrentAnimation();
        this.animationY = 46;
        this.currentState = this.STANDING;
    }
};

Sonic.prototype.startRunRight = function () {
    if (this.currentState != this.RUNNING) {
        this.clearCurrentAnimation();
        this.animationY = 138;
        this.run();
        this.currentState = this.RUNNING;
    }
};

Sonic.prototype.startRunLeft = function () {
    if (this.currentState != this.RUNNING) {
        this.clearCurrentAnimation();
        this.animationY = 92;
        this.run();
        this.currentState = this.RUNNING;
    }
};

Sonic.prototype.startDashRight = function () {
    if (this.currentState != this.DASHING) {
        this.clearCurrentAnimation();
        this.animationY = 230;
        this.dash();
        this.currentState = this.DASHING;
    }
};

Sonic.prototype.startDashLeft = function () {
    if (this.currentState != this.DASHING) {
        this.clearCurrentAnimation();
        this.animationY = 184;
        this.dash();
        this.currentState = this.DASHING;
    }
};

Sonic.prototype.startBallRight = function () {
    if (this.currentState != this.JUMPING) {
        this.clearCurrentAnimation();
        this.animationY = 322;
        this.ball();
        this.currentState = this.JUMPING;
    }
};

Sonic.prototype.startBallLeft = function () {
    if (this.currentState != this.JUMPING) {
        this.clearCurrentAnimation();
        this.animationY = 276;
        this.ball();
        this.currentState = this.JUMPING;
    }
};

Sonic.prototype.startStopRight = function () {
    this.clearCurrentAnimation();
    this.animationY = 414;
    this.stop();
};

Sonic.prototype.startStopLeft = function () {
    this.clearCurrentAnimation();
    this.animationY = 368;
    this.stop();
};

Sonic.prototype.run = function () {
    this.currentAnimationFrame += 1;
    if (this.currentAnimationFrame == this.runAnimationNumberFrame) {
        this.currentAnimationFrame = 0;
    }

    this.animationLoop = setTimeout(function () {
        this.run();
    }.bind(this), 100);
};

Sonic.prototype.dash = function () {
    this.currentAnimationFrame += 1;
    if (this.currentAnimationFrame == this.dashAnimationNumberFrame) {
        this.currentAnimationFrame = 0;
    }

    this.animationLoop = setTimeout(function () {
        this.dash();
    }.bind(this), 100);
};

Sonic.prototype.ball = function () {
    this.currentAnimationFrame += 1;
    if (this.currentAnimationFrame == this.ballAnimationNumberFrame) {
        this.currentAnimationFrame = 0;
    }

    this.animationLoop = setTimeout(function () {
        this.ball();
    }.bind(this), 100);
};

Sonic.prototype.stop = function () {
    this.currentAnimationFrame += 1;

    if (this.currentAnimationFrame == this.stopAnimationNumberFrame) {
        this.currentAnimationFrame = 0;
    }

    this.animationLoop = setTimeout(function () {
        this.stop();
    }.bind(this), 100);
};

Sonic.prototype.animate = function () {
    if (physics.isInAir()) {
        if (physics.speed > 0) {
            this.startBallRight();
        } else if (physics.speed < 0) {
            this.startBallLeft();
        } else {
            if (gamepad.lastDirection == gamepad.LEFT) {
                this.startBallLeft();
            } else {
                this.startBallRight();
            }
        }

    } else if (physics.isStanding()) {
        if (gamepad.lastDirection == gamepad.LEFT) {
            this.standLeft();
        } else {
            this.standRight();
        }
    } else if (physics.isRunningRight()) {
        this.startRunRight();
    } else if (physics.isRunningLeft()) {
        this.startRunLeft();
    } else if (physics.isDashingRight()) {
        this.startDashRight();
    } else if (physics.isDashingLeft()) {
        this.startDashLeft();
    }
}<commit_msg>Delete sonic.js<commit_after><|endoftext|>


<commit_before>var _ = require('lodash'),
  references = require('./references'),
  dom = require('./dom');

/**
 * click handler for adding a component
 * @param {event} e
 */
function addComponent(e) {
  var componentName = e.target.getAttribute('data-component-name');

  e.stopPropagation();
  console.log('adding component: ' + componentName); // todo: actually add the component and render it
}

/**
 * create a new button for each component
 * @param {string} item name
 * @returns {element} buttonEl
 */
function createComponentButton(item) {
  var buttonEl = dom.create(`<button class="add-component" data-component-name="${item}">${item}</button>`);

  buttonEl.addEventListener('click', addComponent);
  return buttonEl;
}

/**
 * map through components, filtering out excluded
 * @param {array} possibleComponents
 * @param {array} [exclude] array of components to exclude
 * @returns {array} array of elements
 */
function getButtons(possibleComponents, exclude) {
  return _.map(possibleComponents, function (item) {
    if (exclude && exclude.length) {
      if (!_.contains(exclude)) {
        return createComponentButton(item);
      }
    } else {
      return createComponentButton(item);
    }
  });
}

/**
 * create pane and buttons
 * @param {object} args
 * @returns {Element}
 */
function createPane(args) {
  var include = args.include,
    exclude = args.exclude,
    allComponents = ['paragraph'], // todo: get list of all components
    tpl =
      `

          +

`,
    pane = dom.create(tpl),
    buttons;

  // figure out what components should be available for adding
  if (include && include.length) {
    buttons = getButtons(include, exclude);
  } else {
    buttons = getButtons(allComponents, exclude);
  }

  // put add components buttons into the pane
  _.each(buttons, function (button) {
    dom.find(pane, '.add-components-pane').appendChild(button);
  });

  return pane;
}

/**
 * match when schema says it's a component list
 * @param {Element} el
 * @param {{ref: string, path: string, data: object}} options
 * @returns {boolean}
 */
function when(el, options) {
  var schema = _.get(options, 'data._schema');

  return schema.hasOwnProperty(references.componentListProperty);
}

/**
 * add "add component" button
 * @param {Element} el
 * @param {{ref: string, path: string, data: object}} options
 * @returns {Element}
 */
function handler(el, options) {
  var args = _.get(options, 'data._schema.' + references.componentListProperty),
    pane, button;

  // if _componentList: true, make the args an object
  args = _.isObject(args) ? args : {};

  // create the pane
  pane = createPane(args);
  button = dom.find(pane, '.open-add-components');

  // add click events to toggle pane
  button.addEventListener('click', function () {
    var addComponentsPane = dom.find(pane, '.add-components-pane');

    button.classList.toggle('open');
    addComponentsPane.classList.toggle('open');
  });

  // add the pane to the end of the component list
  el.appendChild(pane);

  return el;
}

module.exports.when = when;
module.exports.handler = handler;
<commit_msg>remove undefined buttons<commit_after>var _ = require('lodash'),
  references = require('./references'),
  dom = require('./dom');

/**
 * click handler for adding a component
 * @param {event} e
 */
function addComponent(e) {
  var componentName = e.target.getAttribute('data-component-name');

  e.stopPropagation();
  console.log('adding component: ' + componentName); // todo: actually add the component and render it
}

/**
 * create a new button for each component
 * @param {string} item name
 * @returns {element} buttonEl
 */
function createComponentButton(item) {
  var buttonEl = dom.create(`<button class="add-component" data-component-name="${item}">${item}</button>`);

  buttonEl.addEventListener('click', addComponent);
  return buttonEl;
}

/**
 * map through components, filtering out excluded
 * @param {array} possibleComponents
 * @param {array} [exclude] array of components to exclude
 * @returns {array} array of elements
 */
function getButtons(possibleComponents, exclude) {
  return _.compact(_.map(possibleComponents, function (item) {
    if (exclude && exclude.length) {
      if (!_.contains(exclude)) {
        return createComponentButton(item);
      }
    } else {
      return createComponentButton(item);
    }
  }));
}

/**
 * create pane and buttons
 * @param {object} args
 * @returns {Element}
 */
function createPane(args) {
  var include = args.include,
    exclude = args.exclude,
    allComponents = ['paragraph'], // todo: get list of all components
    tpl =
      `

          +

`,
    pane = dom.create(tpl),
    buttons;

  // figure out what components should be available for adding
  if (include && include.length) {
    buttons = getButtons(include, exclude);
  } else {
    buttons = getButtons(allComponents, exclude);
  }

  // put add components buttons into the pane
  _.each(buttons, function (button) {
    dom.find(pane, '.add-components-pane').appendChild(button);
  });

  return pane;
}

/**
 * match when schema says it's a component list
 * @param {Element} el
 * @param {{ref: string, path: string, data: object}} options
 * @returns {boolean}
 */
function when(el, options) {
  var schema = _.get(options, 'data._schema');

  return schema.hasOwnProperty(references.componentListProperty);
}

/**
 * add "add component" button
 * @param {Element} el
 * @param {{ref: string, path: string, data: object}} options
 * @returns {Element}
 */
function handler(el, options) {
  var args = _.get(options, 'data._schema.' + references.componentListProperty),
    pane, button;

  // if _componentList: true, make the args an object
  args = _.isObject(args) ? args : {};

  // create the pane
  pane = createPane(args);
  button = dom.find(pane, '.open-add-components');

  // add click events to toggle pane
  button.addEventListener('click', function () {
    var addComponentsPane = dom.find(pane, '.add-components-pane');

    button.classList.toggle('open');
    addComponentsPane.classList.toggle('open');
  });

  // add the pane to the end of the component list
  el.appendChild(pane);

  return el;
}

module.exports.when = when;
module.exports.handler = handler;
<|endoftext|>


<commit_before>ResLang = {
<<<<<<< HEAD
	'2107' : ['设备回收~', '设备回收~'],
	'1955' : ['任务配置~', '任务配置~'],
	'2232' : ['操作记录~', '操作记录~'],
	'912' : ['增加资费~'],
	'911' : ['修改产品~'],
	'913' : ['修改资费~'],
	'4116' : ['增加费用模板配置~', '编辑模板~'],
	'70' : ['缴费~', '缴费~'],
	'65' : ['报开~', '报开'],
	'66' : ['套餐订购~', '套餐订购~'],
	'67' : ['退订~', '退订~'],
	'29' : ['待处理工单~', '待处理工单~'],
	'3' : ['修改加入订单日期~'],
	'73' : ['调账~', '调账~'],
	'64' : ['报停~', '报停~'],
	'1561' : ['在线用户~', '在线用户~'],
	'4101' : ['项目查询~'],
	'3012' : ['账户产品配置~', '账户产品配置~'],
	'1240' : ['财务配置~'],
	'1279' : ['促销配置~'],
	'4106' : ['项目失效按钮~'],
	'4103' : ['修改项目按钮~'],
	'4102' : ['添加项目按钮~'],
	'4105' : ['项目生效按钮~'],
	'4104' : ['项目小区关联按钮~'],
	'26541' : ['重打受理单~', '重打受理单~'],
	'26540' : ['作废发票~', '作废发票~'],
	'3017' : ['机卡解绑~', '机卡解绑~'],
	'1160' : ['产品管理~', '产品配置~'],
	'83' : ['费用修改~', '费用修改~'],
	'91' : ['修改~', '修改发票~'],
	'88' : ['打印~', '发票打印~'],
	'2000' : ['仓库配置~', '仓库配置~'],
	'1181' : ['不打印标记~', '不打印标记~'],
	'1182' : ['打开打印标记~', '打开打印标记~'],
	'26080' : ['手工发票号修改~', '手工发票号修改~'],
	'112' : ['批量开户~', '批量用户开户~'],
	'111' : ['批量购买配件~', '批量购买配件~'],
	'1500' : ['设备查询~', '设备查询~'],
	'1503' : ['非营业费收取~', '非营业费收取~'],
	'90' : ['购买配件~', '购买配件~'],
	'2005' : ['设备查询~', '设备查询~'],
	'1100' : ['移机~', '移机~'],
	'1179' : ['产品配置~', '产品配置~'],
	'60' : ['开户~', '用户开户~'],
	'61' : ['销户~', '用户销户~'],
	'51' : ['销户~', '客户销户~'],
	'58' : ['更换~', '更换设备~'],
	'3227' : ['发票领用~'],
	'24' : ['作废~', '作废按钮~'],
	'25' : ['提交呼叫~', '提交呼叫~'],
	'26' : ['回单~', '回单按钮~'],
	'27' : ['已完成工单~', '已完成工单~'],
	'14352' : ['变更记录~', '变更记录~'],
	'1283' : ['套餐缴费~', '套餐缴费~'],
	'85' : ['修改流水备注~', '修改流水备注~'],
	'2007' : ['设备盘点~', '设备盘点~'],
	'154' : ['客户等级修改~', '客户等级修改~'],
	'2' : ['系统管理~', '系统管理~'],
	'9' : ['参数配置~', '参数配置~'],
	'23' : ['费用项配置~', '费用项配置~'],
	'15' : ['基本配置~', '基本配置~'],
	'1054' : ['资源管理~', '资源管理~'],
	'4' : ['角色管理~', '角色管理~'],
	'8' : ['机构管理~', '机构管理~'],
	'0' : ['系统根目录~', '系统根目录~'],
	'1' : ['操作员管理~', '操作员管理~'],
	'12' : ['业务配置~', '业务配置~'],
	'13' : ['系统参数配置~', '系统参数'],
	'16' : ['模板~', '模板~'],
	'50' : ['客户开户~', '客户开户'],
	'54' : ['修改~', '修改客户~'],
	'100' : ['营业子系统~', '营业系统菜单~'],
	'26060' : ['取消领用~'],
	'1031' : ['修改停机数~', '修改停机数~'],
	'3206' : ['工单打印~', '工单打印~'],
	'101' : ['设备挂失~', '设备挂失~'],
	'2006' : ['详细~', '详细查询~'],
	'1501' : ['发票查询~', '发票查询~'],
	'3112' : ['修改状态~'],
	'3111' : ['发票结帐~'],
	'3113' : ['取消结帐~'],
	'3114' : ['取消核销~'],
	'3115' : ['发票查询~'],
	'3010' : ['发票入库~'],
	'3007' : ['发票调拨~'],
	'3009' : ['发票核销~'],
	'2004' : ['设备调拨~', '设备调拨~'],
	'3015' : ['灌装~', '灌装~'],
	'3008' : ['订单管理~', '订单管理~'],
	'3002' : ['配置~', '基本配置~'],
	'3005' : ['退库~', '设备退库~'],
	'3003' : ['设备入库~', '设备入库~'],
	'3001' : ['差异管理~', '差异管理~'],
	'3011' : ['设备领用~', '设备领用~'],
	'3006' : ['设备状态管理~', '状态管理~'],
	'3116' : ['详细查询~'],
	'1155' : ['地区管理~', '地区管理~'],
	'28' : ['处理中工单~', '处理中工单~'],
	'10001' : ['单产品订购~', '产品订购~'],
	'10002' : ['产品续订~', '续订~'],
	'10003' : ['产品升级~', '升级~'],
	'3004' : ['规则配置~', '规则配置~'],
	'1557' : ['公告配置~', '公告配置~'],
	'1556' : ['资源组配置~', '资源组配置~'],
	'1003' : ['取消预报停~', '取消预报停~'],
	'156' : ['高级修改~', '高级修改~'],
	'2819' : ['资源管理~', '资源管理~'],
	'69' : ['指令重发~', '指令重发~'],
	'1600' : ['单卡指令~', '单卡指令~'],
	'3110' : ['发票退库~'],
	'26980' : ['工单管理~', '工单管理~'],
	'27000' : ['新增工单~', '新增工单~'],
	'189' : ['高级退订~', '高级退订~'],
	'113' : ['账户充值~', '账户充值~'],
	'114' : ['账户退款~', '账户退款~'],
	'190' : ['超级退订~', '超级退订~'],
	'27020' : ['重置密码~', '重置密码~'],
	'27021' : ['用户名批量修改~', '用户名批量修改~'],
	'27022' : ['汇率配置~', '汇率配置~'],
	'79' : ['刷新指令~', '刷新指令~'],
	'52' : ['过户~', '过户~']
}

// 工具栏国际化
Tools = {
	"gg": "公告~",
	"qtyw": '其它业务~',
	"gj": '工具~',
	"czpz": '重载配置~',
	"czfpsj": '重载发票数据~',
	"qhbm": '切换部门~',
	"qhxt": '切换系统~',
	"grxg": '个人修改~',
	"aqtc": '安全退出~',
	'bz': '帮助~',
	'bsbz': 'BOSS帮助~',
	'gywm': '关于我们~'
}
<commit_msg><commit_after>ResLang = {
	'2107' : ['设备回收~', '设备回收~'],
	'1955' : ['任务配置~', '任务配置~'],
	'2232' : ['操作记录~', '操作记录~'],
	'912' : ['增加资费~'],
	'911' : ['修改产品~'],
	'913' : ['修改资费~'],
	'4116' : ['增加费用模板配置~', '编辑模板~'],
	'70' : ['缴费~', '缴费~'],
	'65' : ['报开~', '报开'],
	'66' : ['套餐订购~', '套餐订购~'],
	'67' : ['退订~', '退订~'],
	'29' : ['待处理工单~', '待处理工单~'],
	'3' : ['修改加入订单日期~'],
	'73' : ['调账~', '调账~'],
	'64' : ['报停~', '报停~'],
	'1561' : ['在线用户~', '在线用户~'],
	'4101' : ['项目查询~'],
	'3012' : ['账户产品配置~', '账户产品配置~'],
	'1240' : ['财务配置~'],
	'1279' : ['促销配置~'],
	'4106' : ['项目失效按钮~'],
	'4103' : ['修改项目按钮~'],
	'4102' : ['添加项目按钮~'],
	'4105' : ['项目生效按钮~'],
	'4104' : ['项目小区关联按钮~'],
	'26541' : ['重打受理单~', '重打受理单~'],
	'26540' : ['作废发票~', '作废发票~'],
	'3017' : ['机卡解绑~', '机卡解绑~'],
	'1160' : ['产品管理~', '产品配置~'],
	'83' : ['费用修改~', '费用修改~'],
	'91' : ['修改~', '修改发票~'],
	'88' : ['打印~', '发票打印~'],
	'2000' : ['仓库配置~', '仓库配置~'],
	'1181' : ['不打印标记~', '不打印标记~'],
	'1182' : ['打开打印标记~', '打开打印标记~'],
	'26080' : ['手工发票号修改~', '手工发票号修改~'],
	'112' : ['批量开户~', '批量用户开户~'],
	'111' : ['批量购买配件~', '批量购买配件~'],
	'1500' : ['设备查询~', '设备查询~'],
	'1503' : ['非营业费收取~', '非营业费收取~'],
	'90' : ['购买配件~', '购买配件~'],
	'2005' : ['设备查询~', '设备查询~'],
	'1100' : ['移机~', '移机~'],
	'1179' : ['产品配置~', '产品配置~'],
	'60' : ['开户~', '用户开户~'],
	'61' : ['销户~', '用户销户~'],
	'51' : ['销户~', '客户销户~'],
	'58' : ['更换~', '更换设备~'],
	'3227' : ['发票领用~'],
	'24' : ['作废~', '作废按钮~'],
	'25' : ['提交呼叫~', '提交呼叫~'],
	'26' : ['回单~', '回单按钮~'],
	'27' : ['已完成工单~', '已完成工单~'],
	'14352' : ['变更记录~', '变更记录~'],
	'1283' : ['套餐缴费~', '套餐缴费~'],
	'85' : ['修改流水备注~', '修改流水备注~'],
	'2007' : ['设备盘点~', '设备盘点~'],
	'154' : ['客户等级修改~', '客户等级修改~'],
	'2' : ['系统管理~', '系统管理~'],
	'9' : ['参数配置~', '参数配置~'],
	'23' : ['费用项配置~', '费用项配置~'],
	'15' : ['基本配置~', '基本配置~'],
	'1054' : ['资源管理~', '资源管理~'],
	'4' : ['角色管理~', '角色管理~'],
	'8' : ['机构管理~', '机构管理~'],
	'0' : ['系统根目录~', '系统根目录~'],
	'1' : ['操作员管理~', '操作员管理~'],
	'12' : ['业务配置~', '业务配置~'],
	'13' : ['系统参数配置~', '系统参数'],
	'16' : ['模板~', '模板~'],
	'50' : ['客户开户~', '客户开户'],
	'54' : ['修改~', '修改客户~'],
	'100' : ['营业子系统~', '营业系统菜单~'],
	'26060' : ['取消领用~'],
	'1031' : ['修改停机数~', '修改停机数~'],
	'3206' : ['工单打印~', '工单打印~'],
	'101' : ['设备挂失~', '设备挂失~'],
	'2006' : ['详细~', '详细查询~'],
	'1501' : ['发票查询~', '发票查询~'],
	'3112' : ['修改状态~'],
	'3111' : ['发票结帐~'],
	'3113' : ['取消结帐~'],
	'3114' : ['取消核销~'],
	'3115' : ['发票查询~'],
	'3010' : ['发票入库~'],
	'3007' : ['发票调拨~'],
	'3009' : ['发票核销~'],
	'2004' : ['设备调拨~', '设备调拨~'],
	'3015' : ['灌装~', '灌装~'],
	'3008' : ['订单管理~', '订单管理~'],
	'3002' : ['配置~', '基本配置~'],
	'3005' : ['退库~', '设备退库~'],
	'3003' : ['设备入库~', '设备入库~'],
	'3001' : ['差异管理~', '差异管理~'],
	'3011' : ['设备领用~', '设备领用~'],
	'3006' : ['设备状态管理~', '状态管理~'],
	'3116' : ['详细查询~'],
	'1155' : ['地区管理~', '地区管理~'],
	'28' : ['处理中工单~', '处理中工单~'],
	'10001' : ['单产品订购~', '产品订购~'],
	'10002' : ['产品续订~', '续订~'],
	'10003' : ['产品升级~', '升级~'],
	'3004' : ['规则配置~', '规则配置~'],
	'1557' : ['公告配置~', '公告配置~'],
	'1556' : ['资源组配置~', '资源组配置~'],
	'1003' : ['取消预报停~', '取消预报停~'],
	'156' : ['高级修改~', '高级修改~'],
	'2819' : ['资源管理~', '资源管理~'],
	'69' : ['指令重发~', '指令重发~'],
	'1600' : ['单卡指令~', '单卡指令~'],
	'3110' : ['发票退库~'],
	'26980' : ['工单管理~', '工单管理~'],
	'27000' : ['新增工单~', '新增工单~'],
	'189' : ['高级退订~', '高级退订~'],
	'113' : ['账户充值~', '账户充值~'],
	'114' : ['账户退款~', '账户退款~'],
	'190' : ['超级退订~', '超级退订~'],
	'27020' : ['重置密码~', '重置密码~'],
	'27021' : ['用户名批量修改~', '用户名批量修改~'],
	'27022' : ['汇率配置~', '汇率配置~'],
	'79' : ['刷新指令~', '刷新指令~'],
	'52' : ['过户~', '过户~']
}

// 工具栏国际化
Tools = {
	"gg": "公告~",
	"qtyw": '其它业务~',
	"gj": '工具~',
	"czpz": '重载配置~',
	"czfpsj": '重载发票数据~',
	"qhbm": '切换部门~',
	"qhxt": '切换系统~',
	"grxg": '个人修改~',
	"aqtc": '安全退出~',
	'bz': '帮助~',
	'bsbz': 'BOSS帮助~',
	'gywm': '关于我们~'
}
<|endoftext|>


<commit_before>'use strict';

angular.module('arachne.directives')

/**
 * Shows a gridmap constructed from the current searches
 * agg_geogrid facet.
 *
 * @author: David Neugebauer
 * @author: Daniel M. de Oliveira
 */
.directive('arGridMap', ['$filter', 'searchService', 'mapService',
function($filter, searchService, mapService) {
    return {
        restrict: 'A',
        scope: {
            baselayers: '='
        },
        link: function(scope, element) {

            var currentGridLayers = [];
            var baseLinkRef = document.getElementById('baseLink').getAttribute("href");

            // Set map view to center coords with zoomlevel
            var initializeView = function(lat,lng,zoom) {
                var lt = lat || 40;
                var lg = lng || -10;
                var zm = zoom || 3;
                map.setView([lt, lg], zm);
            };

            /**
             * Guesses a good geohash precision value from the zoomlevel
             * "zoom". The returned value can be used as "ghprec"-param in
             * search queries
             */
            var getGhprecFromZoom = function(zoom) {
                var result = null;

                switch (zoom) {
                    case 0:
                    case 1:
                        result = 1;
                        break;
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                        result = 2;
                        break;
                    case 6:
                    case 7:
                    case 8:
                        result = 3;
                        break;
                    case 9:
                    case 10:
                        result = 4;
                        break;
                    case 11:
                    case 12:
                        result = 5;
                        break;
                    case 13:
                    case 14:
                    case 15:
                        result = 6;
                        break;
                    case 16:
                    case 17:
                    case 18:
                        result = 7;
                        break;
                    default:
                        break;
                }
                return result;
            };

            var getBboxFromBounds = function(bounds) {
                var southEast = bounds.getSouthEast();
                var northWest = bounds.getNorthWest();
                return [northWest.lat, northWest.lng, southEast.lat, southEast.lng]
            };

            var calculateHalfWidth = function(ghprec) {
                var parity = ghprec % 2;
                return 90 / Math.pow(2, ((5*ghprec + parity - 2) / 2) );
            }

            var calculateHalfHeight = function(ghprec) {
                var parity = ghprec % 2;
                return 90 / Math.pow(2, ((5*ghprec - parity) / 2) );
            }

            var calculateOpts = function(hue) {

                return {
                    color: "hsl(" + hue + ", 70%, 75%)",
                    stroke: false,
                    weight: 1,
                    clickable: false
                };
            }

            var makeBoxesLayer = function(coords, count, max, ghprec) {
                var halfHeight=calculateHalfHeight(ghprec)
                var halfWidth =calculateHalfWidth(ghprec)

                // coordinates for the box's corners
                var southwest = [(coords[0]-halfHeight), (coords[1]-halfWidth)];
                var northeast = [(coords[0]+halfHeight), (coords[1]+halfWidth)];
                // determine a color for the box
                var ratio = count / max;
                var hue = (1.0 - ratio) * 240; // 0-240 gives a 5-color heatmap from blue to red
                var rect = L.rectangle([southwest, northeast], calculateOpts(hue));
                return rect;
            };

            var makeLabelsLayer = function(coords, count, gridElementBounds) {
                var countStr = $filter('number')(count);
                var opts = {
                    className: 'ar-map-geogrid-label',
                    html: '
' + countStr + '
',
                }
                var label = L.marker(coords, { icon: L.divIcon(opts) });
                var query = searchService.currentQuery().setParam('bbox', getBboxFromBounds(gridElementBounds).join(','));
                label.bindPopup('' + countStr + ' Objekte bei (' + coords[0] + ', ' + coords[1] + ')');

                label.on('mouseover', function(e) {
                    label.openPopup();
                });
                return label;
            };

            var removeCurrentGridLayers = function() {
                if (currentGridLayers) {
                    for (var i = 0; i < currentGridLayers.length; i++) {
                        map.removeLayer(currentGridLayers[i]);
                    }
                }
            };

            var drawGrid = function(boxesToDraw,ghprec) {

                // find maximum facet value
                var counts = boxesToDraw.map(function(elem) {
                    return elem.count;
                });
                var max = Math.max.apply(null, counts);

                // compute the distance from the box's center to it's sides

                for (var i = 0; i < boxesToDraw.length; i++) {
                    var coords = angular.fromJson(boxesToDraw[i].value);
                    var count = boxesToDraw[i].count;

                    var boxesLayer = makeBoxesLayer(coords, count, max, ghprec);
                    var labelsLayer = makeLabelsLayer(coords, count, boxesLayer.getBounds())

                    labelsLayer.addTo(map);
                    boxesLayer.addTo(map);

                    currentGridLayers.push(boxesLayer);
                    currentGridLayers.push(labelsLayer);
                }
            };

            /**
             * Adjusts currentQuery to the current viewport.
             * The query gets executed and a new grid gets drawn
             * with layers based on the results.
             */
            var recalculateGridForViewport = function(){
                currentQuery.ghprec = getGhprecFromZoom(map.getZoom());
                currentQuery.bbox = getBboxFromBounds(map.getBounds()).join(',');

                searchService.setCurrentQuery(currentQuery);
                searchService.getCurrentPage().then(function(entities){

                    removeCurrentGridLayers();

                    var boxesToDraw=[];
                    var agg_geogrid = searchService.getFacet("agg_geogrid");
                    if (agg_geogrid) boxesToDraw=agg_geogrid.values;

                    if (boxesToDraw.length!=0)
                        drawGrid(boxesToDraw,currentQuery.ghprec);
                });
            };

            // on link

            var currentQuery = searchService.currentQuery();
            if (!currentQuery.q) currentQuery.q = '*';

            var baselayerName = currentQuery.baselayer || "osm";

            var map = mapService.initializeMap(
                element.attr('id'),
                {minZoom: 3} // 3 is to prevent wrong bbox searches
                             // when the window is bigger than the world
            );
            // Add baselayers and activate one, given by url
            // parameter "baselayer" or a default value
            mapService.setBaselayers(scope.baselayers);
            mapService.activateBaselayer(baselayerName);
            initializeView(currentQuery.lat,currentQuery.lng,currentQuery.zoom);
            recalculateGridForViewport();

            // Hook for redrawing the grid on zoom and move events
            map.on('moveend', function() {
                recalculateGridForViewport();
            });
        }
    };
}]);<commit_msg>Minor code structure improvements.<commit_after>'use strict';

angular.module('arachne.directives')

/**
 * Shows a gridmap constructed from the current searches
 * agg_geogrid facet.
 *
 * @author: David Neugebauer
 * @author: Daniel M. de Oliveira
 */
.directive('arGridMap', ['$filter', 'searchService', 'mapService',
function($filter, searchService, mapService) {
    return {
        restrict: 'A',
        scope: {
            baselayers: '='
        },
        link: function(scope, element) {

            var currentGridLayers = [];
            var baseLinkRef = document.getElementById('baseLink').getAttribute("href");

            /**
             * Set map view to center coords with zoomlevel
             */
            var initializeView = function(lat,lng,zoom) {
                var lt = lat || 40;
                var lg = lng || -10;
                var zm = zoom || 3;
                map.setView([lt, lg], zm);
            };

            /**
             * Guesses a good geohash precision value from the zoomlevel
             * "zoom". The returned value can be used as "ghprec"-param in
             * search queries
             */
            var getGhprecFromZoom = function(zoomLevel) {
                var zl=zoomLevel;

                var ghprecForZoomLevel =
                    [1,1,2,2,2,2,3,3,3,4,4,5,5,6,6,6,7,7,7];

                if (zl>18) zl=18;
                return ghprecForZoomLevel[zl];
            };

            var getBboxFromBounds = function(bounds) {
                var southEast = bounds.getSouthEast();
                var northWest = bounds.getNorthWest();
                return [northWest.lat, northWest.lng, southEast.lat, southEast.lng]
            };

            var calculateHalfWidth = function(ghprec) {
                var parity = ghprec % 2;
                return 90 / Math.pow(2, ((5*ghprec + parity - 2) / 2) );
            }

            var calculateHalfHeight = function(ghprec) {
                var parity = ghprec % 2;
                return 90 / Math.pow(2, ((5*ghprec - parity) / 2) );
            }

            var calculateOpts = function(hue) {

                return {
                    color: "hsl(" + hue + ", 70%, 75%)",
                    stroke: false,
                    weight: 1,
                    clickable: false
                };
            }

            var makeBoxesLayer = function(coords, count, max, ghprec) {
                var halfHeight=calculateHalfHeight(ghprec)
                var halfWidth =calculateHalfWidth(ghprec)

                // coordinates for the box's corners
                var southwest = [(coords[0]-halfHeight), (coords[1]-halfWidth)];
                var northeast = [(coords[0]+halfHeight), (coords[1]+halfWidth)];
                // determine a color for the box
                var ratio = count / max;
                var hue = (1.0 - ratio) * 240; // 0-240 gives a 5-color heatmap from blue to red
                var rect = L.rectangle([southwest, northeast], calculateOpts(hue));
                return rect;
            };

            var makeLabelsLayer = function(coords, count, gridElementBounds) {
                var countStr = $filter('number')(count);
                var opts = {
                    className: 'ar-map-geogrid-label',
                    html: '
' + countStr + '
',
                }
                var label = L.marker(coords, { icon: L.divIcon(opts) });
                var query = searchService.currentQuery().setParam('bbox', getBboxFromBounds(gridElementBounds).join(','));
                label.bindPopup('' + countStr + ' Objekte bei (' + coords[0] + ', ' + coords[1] + ')');

                label.on('mouseover', function(e) {
                    label.openPopup();
                });
                return label;
            };

            var removeCurrentGridLayers = function() {
                if (currentGridLayers) {
                    for (var i = 0; i < currentGridLayers.length; i++) {
                        map.removeLayer(currentGridLayers[i]);
                    }
                }
            };

            var findMaximumFacetValue = function(boxesToDraw) {

                var counts = boxesToDraw.map(function(elem) {
                    return elem.count;
                });
                return Math.max.apply(null, counts);
            }

            var drawGrid = function(boxesToDraw,ghprec) {

                for (var i = 0; i < boxesToDraw.length; i++) {
                    var coords = angular.fromJson(boxesToDraw[i].value);
                    var count = boxesToDraw[i].count;

                    var boxesLayer = makeBoxesLayer(
                        coords, count, findMaximumFacetValue(boxesToDraw), ghprec);
                    var labelsLayer = makeLabelsLayer(
                        coords, count, boxesLayer.getBounds())

                    labelsLayer.addTo(map);
                    boxesLayer.addTo(map);

                    currentGridLayers.push(boxesLayer);
                    currentGridLayers.push(labelsLayer);
                }
            };

            /**
             * Adjusts currentQuery to the current viewport.
             * The query gets executed and a new grid gets drawn
             * with layers based on the results.
             */
            var recalculateGridForViewport = function(){
                currentQuery.ghprec = getGhprecFromZoom(map.getZoom());
                currentQuery.bbox = getBboxFromBounds(map.getBounds()).join(',');

                searchService.setCurrentQuery(currentQuery);
                searchService.getCurrentPage().then(function(entities){

                    removeCurrentGridLayers();

                    var boxesToDraw=[];
                    var agg_geogrid = searchService.getFacet("agg_geogrid");
                    if (agg_geogrid) boxesToDraw=agg_geogrid.values;

                    if (boxesToDraw.length!=0)
                        drawGrid(boxesToDraw,currentQuery.ghprec);
                });
            };

            // on link

            var currentQuery = searchService.currentQuery();
            if (!currentQuery.q) currentQuery.q = '*';

            var baselayerName = currentQuery.baselayer || "osm";

            var map = mapService.initializeMap(
                element.attr('id'),
                {minZoom: 3} // 3 is to prevent wrong bbox searches
                             // when the window is bigger than the world
            );
            // Add baselayers and activate one, given by url
            // parameter "baselayer" or a default value
            mapService.setBaselayers(scope.baselayers);
            mapService.activateBaselayer(baselayerName);
            initializeView(currentQuery.lat,currentQuery.lng,currentQuery.zoom);
            recalculateGridForViewport();

            // Hook for redrawing the grid on zoom and move events
            map.on('moveend', function() {
                recalculateGridForViewport();
            });
        }
    };
}]);<|endoftext|>


<commit_before>'use strict';

const got = require('got');
const Table = require('cli-table2');
const chalk = require('chalk');
const moment = require('moment');
const truncate = require('truncate');
const handleError = require('./util/handleError');

exports.command = 'search <query...>';
exports.describe = 'Search npms.io for packages.';
exports.builder = (yargs) =>
    yargs
    .strict()
    .usage('Usage: $0 search <query...> [options]\n\nSearch npms.io for packages.\nFor advances filters and modifiers visit https://api-docs.npms.io/#api-search-query.')
    .example('$0 search cross spawn', 'Search for "cross spawn"')
    .example('$0 search cross spawn --output json', 'Search for "cross spawn" and print results as JSON')
    .example('$0 search sass keywords:gulpplugin', 'Search for "sass" packages that contain the "gulpplugin" keywords')
    .demand(1)
    .options({
        from: {
            alias: 'f',
            describe: 'The offset in which to start searching from',
            default: 0,
            type: 'number',
        },
        size: {
            alias: 's',
            describe: 'The total number of results to return',
            default: 10,
            type: 'number',
        },
        output: {
            alias: 'o',
            describe: 'Format the results in a table or as JSON',
            default: 'table',
        },
        api: {
            describe: 'The API url',
            default: 'https://api.npms.io/v2',
        },
    });

exports.handler = (argv) => {
    got(`${argv.api}/search`, {
        json: true,
        query: JSON.parse(JSON.stringify({
            q: argv.query.join(' '),
            from: argv.from,
            size: argv.size,
        })),
    })
    .then((res) => {
        if (argv.output === 'json') {
            console.log(JSON.stringify(res.body.results, null, 2));
            return;
        }

        if (!res.body.results.length) {
            console.log(chalk.red(`No matches found for: ${chalk.white.bold(argv.query.join(' '))}`));
            return;
        }

        const table = new Table({ head: ['Package', 'Quality', 'Popularity', 'Maintenance', 'Score'] });

        table.push.apply(table, res.body.results.map((item) => {
            const pkg = item.package;

            const packageColumn = [
                `${chalk.bold(pkg.name)} • ${chalk.dim(pkg.links.repository || pkg.links.npm)}`,
                chalk.gray(truncate(pkg.description, 80, { ellipsis: '...' })),
                chalk.dim(`updated ${moment(pkg.date).fromNow()} by ${pkg.publisher.username}`),
            ].join('\n');

            const scoreColumns = ['quality', 'popularity', 'maintenance']
            .map((score) => ({ hAlign: 'center', vAlign: 'center', content: Math.round(item.score.detail[score] * 100) }))
            .concat([{ hAlign: 'center', vAlign: 'center', content: chalk.green(Math.round(item.score.final * 100)) }]);

            return [packageColumn].concat(scoreColumns);
        }));

        console.log(table.toString());
    })
    .then(() => { process.exitCode = 0; })
    .catch((err) => handleError(err));
};
<commit_msg>Add output `choices` to search command.<commit_after>'use strict';

const got = require('got');
const Table = require('cli-table2');
const chalk = require('chalk');
const moment = require('moment');
const truncate = require('truncate');
const handleError = require('./util/handleError');

exports.command = 'search <query...>';
exports.describe = 'Search npms.io for packages.';
exports.builder = (yargs) =>
    yargs
    .strict()
    .usage('Usage: $0 search <query...> [options]\n\nSearch npms.io for packages.\nFor advances filters and modifiers visit https://api-docs.npms.io/#api-search-query.')
    .example('$0 search cross spawn', 'Search for "cross spawn"')
    .example('$0 search cross spawn --output json', 'Search for "cross spawn" and print results as JSON')
    .example('$0 search sass keywords:gulpplugin', 'Search for "sass" packages that contain the "gulpplugin" keywords')
    .demand(1)
    .options({
        from: {
            alias: 'f',
            describe: 'The offset in which to start searching from',
            default: 0,
            type: 'number',
        },
        size: {
            alias: 's',
            describe: 'The total number of results to return',
            default: 10,
            type: 'number',
        },
        output: {
            alias: 'o',
            describe: 'Format the results in a table or as JSON',
            default: 'table',
            choices: ['table', 'json'],
        },
        api: {
            describe: 'The API url',
            default: 'https://api.npms.io/v2',
        },
    });

exports.handler = (argv) => {
    got(`${argv.api}/search`, {
        json: true,
        query: JSON.parse(JSON.stringify({
            q: argv.query.join(' '),
            from: argv.from,
            size: argv.size,
        })),
    })
    .then((res) => {
        if (argv.output === 'json') {
            console.log(JSON.stringify(res.body.results, null, 2));
            return;
        }

        if (!res.body.results.length) {
            console.log(chalk.red(`No matches found for: ${chalk.white.bold(argv.query.join(' '))}`));
            return;
        }

        const table = new Table({ head: ['Package', 'Quality', 'Popularity', 'Maintenance', 'Score'] });

        table.push.apply(table, res.body.results.map((item) => {
            const pkg = item.package;

            const packageColumn = [
                `${chalk.bold(pkg.name)} • ${chalk.dim(pkg.links.repository || pkg.links.npm)}`,
                chalk.gray(truncate(pkg.description, 80, { ellipsis: '...' })),
                chalk.dim(`updated ${moment(pkg.date).fromNow()} by ${pkg.publisher.username}`),
            ].join('\n');

            const scoreColumns = ['quality', 'popularity', 'maintenance']
            .map((score) => ({ hAlign: 'center', vAlign: 'center', content: Math.round(item.score.detail[score] * 100) }))
            .concat([{ hAlign: 'center', vAlign: 'center', content: chalk.green(Math.round(item.score.final * 100)) }]);

            return [packageColumn].concat(scoreColumns);
        }));

        console.log(table.toString());
    })
    .then(() => { process.exitCode = 0; })
    .catch((err) => handleError(err));
};
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import {merge, of} from 'rxjs'
import {mapTo, delay} from 'rxjs/operators'
import DefaultPane from 'part:@sanity/components/panes/default'
import Spinner from 'part:@sanity/components/loading/spinner'
import styles from './styles/LoadingPane.css'

function getWaitMessages(path) {
  const thresholds = [{ms: 300, message: 'Loading…'}, {ms: 5000, message: 'Still loading…'}]

  if (__DEV__) {
    const message = [
      'Check console for errors?',
      'Is your observable/promise resolving?',
      path.length > 0 ? `Structure path: ${path.join(' ➝ ')}` : ''
    ]

    thresholds.push({
      ms: 10000,
      message: message.join('\n')
    })
  }

  const src = of(null)
  return merge(
    ...thresholds.map(({ms, message}) =>
      src.pipe(
        mapTo(message),
        delay(ms)
      )
    )
  )
}

export default class LoadingPane extends React.PureComponent {
  static propTypes = {
    isSelected: PropTypes.bool.isRequired,
    isCollapsed: PropTypes.bool.isRequired,
    onExpand: PropTypes.func,
    onCollapse: PropTypes.func,
    path: PropTypes.arrayOf(PropTypes.string),
    index: PropTypes.number
  }

  static defaultProps = {
    path: [],
    onExpand: undefined,
    onCollapse: undefined
  }

  state = {message: 'Loading…'}

  componentDidMount() {
    this.subscription = getWaitMessages(this.props.path).subscribe(this.updateStatus)
  }

  componentWillUnmount() {
    if (this.subscription) {
      this.subscription.unsubscribe()
    }
  }

  updateStatus = message => {
    this.setState({message})
  }

  render() {
    const {isSelected, isCollapsed, onCollapse, onExpand} = this.props
    const {message} = this.state

    return (
      <DefaultPane
        title={'\u00a0'} // Non-breaking space
        isSelected={isSelected}
        isCollapsed={isCollapsed}
        onCollapse={onCollapse}
        onExpand={onExpand}
        index={this.props.index}
      >
        {/* div wrapper to match styling of documents list pane - prevents spinner
          * from jumping to new position when pane definition is loaded */}

          <Spinner center message={message} />

      </DefaultPane>
    )
  }
}
<commit_msg>[desk-tool] Fix loading indicator being cut at top (#1324)<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import {merge, of} from 'rxjs'
import {mapTo, delay} from 'rxjs/operators'
import DefaultPane from 'part:@sanity/components/panes/default'
import Spinner from 'part:@sanity/components/loading/spinner'
import styles from './styles/LoadingPane.css'

function getWaitMessages(path) {
  const thresholds = [{ms: 300, message: 'Loading…'}, {ms: 5000, message: 'Still loading…'}]

  if (__DEV__) {
    const message = [
      'Check console for errors?',
      'Is your observable/promise resolving?',
      path.length > 0 ? `Structure path: ${path.join(' ➝ ')}` : ''
    ]

    thresholds.push({
      ms: 10000,
      message: message.join('\n')
    })
  }

  const src = of(null)
  return merge(
    ...thresholds.map(({ms, message}) =>
      src.pipe(
        mapTo(message),
        delay(ms)
      )
    )
  )
}

export default class LoadingPane extends React.PureComponent {
  static propTypes = {
    isSelected: PropTypes.bool.isRequired,
    isCollapsed: PropTypes.bool.isRequired,
    onExpand: PropTypes.func,
    onCollapse: PropTypes.func,
    path: PropTypes.arrayOf(PropTypes.string),
    index: PropTypes.number
  }

  static defaultProps = {
    path: [],
    onExpand: undefined,
    onCollapse: undefined
  }

  state = {message: 'Loading…'}

  componentDidMount() {
    this.subscription = getWaitMessages(this.props.path).subscribe(this.updateStatus)
  }

  componentWillUnmount() {
    if (this.subscription) {
      this.subscription.unsubscribe()
    }
  }

  updateStatus = message => {
    this.setState({message})
  }

  render() {
    const {isSelected, isCollapsed, onCollapse, onExpand} = this.props
    const {message} = this.state

    return (
      <DefaultPane
        title={'\u00a0'} // Non-breaking space
        isScrollable={false}
        isSelected={isSelected}
        isCollapsed={isCollapsed}
        onCollapse={onCollapse}
        onExpand={onExpand}
        index={this.props.index}
      >
        {/* div wrapper to match styling of documents list pane - prevents spinner
         * from jumping to new position when pane definition is loaded */}

          <Spinner center message={message} />

      </DefaultPane>
    )
  }
}
<|endoftext|>