<commit_before>'use strict';

/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */

var module = angular.module('editor.drive', ['editor.gapi']);

module.service('drive', ['$q', '$cacheFactory', 'googleApi', 'applicationId', function($q, $cacheFactory, googleApi, applicationId) {

  // Only fetch fields that we care about
  var DEFAULT_FIELDS = 'id,title,mimeType,userPermission,editable,copyable,shared,fileSize';

  var cache = $cacheFactory('files');

  /**
   * Combines metadata & content into a single object & caches the result
   *
   * @param {Object} metadata File metadata
   * @param {String} content File content
   * @return {Object} combined object
   */
  var combineAndStoreResults = function(metadata, content) {
    var file = {
      metadata: metadata,
      content: content
    };
    cache.put(metadata.id, file);
    return file;
  };

  /**
   * Load a file from Drive. Fetches both the metadata & content in parallel.
   *
   * @param {String} fileID ID of the file to load
   * @return {Promise} promise that resolves to an object containing the file metadata & content
   */
  this.loadFile = function(fileId) {
    var file = cache.get(fileId);
    if (file) {
      return $q.when(file);
    }
    return googleApi.then(function(gapi) {
      var metadataRequest = gapi.client.drive.files.get({
        fileId: fileId,
        fields: DEFAULT_FIELDS
      });
      var contentRequest = gapi.client.drive.files.get({
        fileId: fileId,
        alt: 'media'
      });
      return $q.all([$q.when(metadataRequest), $q.when(contentRequest)]);
    }).then(function(responses) {
      return combineAndStoreResults(responses[0].result, responses[1].body);
    });
  };

 /**
   * Save a file to Drive using the mutlipart upload protocol.
   *
   * @param {Object} metadata File metadata to save
   * @param {String} content File content
   * @return {Promise} promise that resolves to an object containing the current file metadata & content
   */
  this.saveFile = function(metadata, content) {
    return googleApi.then(function(gapi) {
      var path;
      var method;

      if (metadata.id) {
        path = '/upload/drive/v2/files/' + encodeURIComponent(metadata.id);
        method = 'PUT';
      } else {
        path = '/upload/drive/v2/files';
        method = 'POST';
      }

      var multipart = new MultiPartBuilder()
        .append('application/json', JSON.stringify(metadata))
        .append(metadata.mimeType, content)
        .finish();

      var uploadRequest = gapi.client.request({
        path: path,
        method: method,
        params: {
          uploadType: 'multipart',
          fields: DEFAULT_FIELDS
        },
        headers: { 'Content-Type' : multipart.type },
        body: multipart.body
      });
      return $q.when(uploadRequest);
    }).then(function(response) {
      return combineAndStoreResults(response.result, content);
    });
  };

  /**
   * Displays the Drive file picker configured for selecting text files
   *
   * @return {Promise} Promise that resolves with the ID of the selected file
   */
  this.showPicker = function() {
    return googleApi.then(function(gapi) {
      var deferred = $q.defer();
      var view = new google.picker.View(google.picker.ViewId.DOCS);
      view.setMimeTypes('text/plain');
      var picker = new google.picker.PickerBuilder()
        .setAppId(applicationId)
        .setOAuthToken(gapi.auth.getToken().access_token)
        .addView(view)
        .setCallback(function(data) {
          if (data.action == 'picked') {
            var id = data.docs[0].id;
            deferred.resolve(id);
          } else if (data.action == 'cancel') {
            deferred.reject();
          }
        })
        .build();
      picker.setVisible(true);
      return deferred.promise;
    });
  };

  /**
   * Displays the Drive sharing dialog
   *
   * @param {String} id ID of the file to share
   */
  this.showSharing = function(id) {
    return googleApi.then(function(gapi) {
      //var deferred = $q.defer();
      var share = new gapi.drive.share.ShareClient(applicationId);
      share.setItemIds([id]);
      share.showSettingsDialog();
      //return deferred.promise;
    });
  };

}]);
<commit_msg>Initial team drive support<commit_after>'use strict';

/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */

var module = angular.module('editor.drive', ['editor.gapi']);

module.service('drive', ['$q', '$cacheFactory', 'googleApi', 'applicationId', function($q, $cacheFactory, googleApi, applicationId) {

  // Only fetch fields that we care about
  var DEFAULT_FIELDS = 'id,title,mimeType,userPermission,editable,copyable,shared,fileSize';

  var cache = $cacheFactory('files');

  /**
   * Combines metadata & content into a single object & caches the result
   *
   * @param {Object} metadata File metadata
   * @param {String} content File content
   * @return {Object} combined object
   */
  var combineAndStoreResults = function(metadata, content) {
    var file = {
      metadata: metadata,
      content: content
    };
    cache.put(metadata.id, file);
    return file;
  };

  /**
   * Load a file from Drive. Fetches both the metadata & content in parallel.
   *
   * @param {String} fileID ID of the file to load
   * @return {Promise} promise that resolves to an object containing the file metadata & content
   */
  this.loadFile = function(fileId) {
    var file = cache.get(fileId);
    if (file) {
      return $q.when(file);
    }
    return googleApi.then(function(gapi) {
      var metadataRequest = gapi.client.drive.files.get({
        fileId: fileId,
        supportsTeamDrives: true,
        fields: DEFAULT_FIELDS
      });
      var contentRequest = gapi.client.drive.files.get({
        fileId: fileId,
        supportsTeamDrives: true,
        alt: 'media'
      });
      return $q.all([$q.when(metadataRequest), $q.when(contentRequest)]);
    }).then(function(responses) {
      return combineAndStoreResults(responses[0].result, responses[1].body);
    });
  };

 /**
   * Save a file to Drive using the mutlipart upload protocol.
   *
   * @param {Object} metadata File metadata to save
   * @param {String} content File content
   * @return {Promise} promise that resolves to an object containing the current file metadata & content
   */
  this.saveFile = function(metadata, content) {
    return googleApi.then(function(gapi) {
      var path;
      var method;

      if (metadata.id) {
        path = '/upload/drive/v2/files/' + encodeURIComponent(metadata.id);
        method = 'PUT';
      } else {
        path = '/upload/drive/v2/files';
        method = 'POST';
      }

      var multipart = new MultiPartBuilder()
        .append('application/json', JSON.stringify(metadata))
        .append(metadata.mimeType, content)
        .finish();

      var uploadRequest = gapi.client.request({
        path: path,
        method: method,
        params: {
          uploadType: 'multipart',
          supportsTeamDrives: true,
          fields: DEFAULT_FIELDS
        },
        headers: { 'Content-Type' : multipart.type },
        body: multipart.body
      });
      return $q.when(uploadRequest);
    }).then(function(response) {
      return combineAndStoreResults(response.result, content);
    });
  };

  /**
   * Displays the Drive file picker configured for selecting text files
   *
   * @return {Promise} Promise that resolves with the ID of the selected file
   */
  this.showPicker = function() {
    return googleApi.then(function(gapi) {
      var deferred = $q.defer();
      var view = new google.picker.View(google.picker.ViewId.DOCS);
      view.setMimeTypes('text/plain');
      var picker = new google.picker.PickerBuilder()
        .setAppId(applicationId)
        .setOAuthToken(gapi.auth.getToken().access_token)
        .addView(view)
        .setCallback(function(data) {
          if (data.action == 'picked') {
            var id = data.docs[0].id;
            deferred.resolve(id);
          } else if (data.action == 'cancel') {
            deferred.reject();
          }
        })
        .build();
      picker.setVisible(true);
      return deferred.promise;
    });
  };

  /**
   * Displays the Drive sharing dialog
   *
   * @param {String} id ID of the file to share
   */
  this.showSharing = function(id) {
    return googleApi.then(function(gapi) {
      //var deferred = $q.defer();
      var share = new gapi.drive.share.ShareClient(applicationId);
      share.setItemIds([id]);
      share.showSettingsDialog();
      //return deferred.promise;
    });
  };

}]);
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { reduxForm, Field, stopSubmit } from 'redux-form';

import styles from './styles/index.scss';
import Button from 'components/Button';

const CREATE_GROUP_FORM = 'createGroup';

const renderInputField = ({ input, label, placeholder, meta: { touched, error } }) => (

      {label}

    <input className="form-control" {...input} placeholder={placeholder} />
    {touched && <div className={`text-danger ${styles.error}`}>{error}
}

);

const renderSelectField = ({ input, label, placeholder, meta: { touched, error } }) => (

      {label}

    <select {...input} placeholder={placeholder}>
      <option></option>
      <option value="0">Lunes</option>
      <option value="1">Martes</option>
      <option value="2">Miércoles</option>
      <option value="3">Jueves</option>
      <option value="4">Viernes</option>
      <option value="5">Sábado</option>
      <option value="6">Domingo</option>
    </select>
    {touched && <div className={`text-danger ${styles.error}`}>{error}
}

);

const required = value => value ? undefined : 'no puede estar en blanco';

const validate = values => {
  const errors = {};

  if (!values.name) {
    errors.name = required(values.name);
  }

  if (!values.delivery) {
    errors.delivery = required(values.delivery);
  }

  if (!values.confirmation) {
    errors.confirmation = required(values.confirmation);
  }

  return errors;
};

class CreateGroupForm extends Component {
  static propTypes = {
    handleSubmit: PropTypes.func.isRequired,
    stopSubmit: PropTypes.func.isRequired,
    errors: PropTypes.object,
    submitting: PropTypes.bool,
  }

  constructor(props) {
    super(props);
  }

  render() {
    const { handleSubmit, submitting } = this.props;

    return (
      <form onSubmit={handleSubmit}>
        <Field
          name="name"
          component={renderInputField}
          placeholder="Elige un nombre para tu grupo de compra"
          label="Nombre del grupo"
        />
        <Field
          name="delivery"
          component={renderSelectField}
          label="Día de entrega"
          placeholder="Especifica el día de entrega de la compra"
        />
        <Field
          name="confirmation"
          component={renderSelectField}
          label="Día de confirmación"
          placeholder="Especifica el día de confirmación de la compra"
        />
        <Button
          type="submit"
          primary
          disabled={submitting}
        >Crear grupo</Button>
      </form>
    );
  }
}

const reduxFormProps = {
  form: CREATE_GROUP_FORM,
  validate
};

const mapStateToProps = (state) => {
  const { form: allForms, groupsReducer: { errors } } = state;

  const form = allForms[CREATE_GROUP_FORM];

  const newState = { errors };

  if (!form) return newState;

  return { ...newState, submitting: form.submitting };
};

export default compose(
  reduxForm(reduxFormProps),
  connect(mapStateToProps, { stopSubmit })
)(CreateGroupForm);
<commit_msg>Switch delivery and confirmation fields<commit_after>import React, { Component, PropTypes } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { reduxForm, Field, stopSubmit } from 'redux-form';

import styles from './styles/index.scss';
import Button from 'components/Button';

const CREATE_GROUP_FORM = 'createGroup';

const renderInputField = ({ input, label, placeholder, meta: { touched, error } }) => (

      {label}

    <input className="form-control" {...input} placeholder={placeholder} />
    {touched && <div className={`text-danger ${styles.error}`}>{error}
}

);

const renderSelectField = ({ input, label, placeholder, meta: { touched, error } }) => (

      {label}

    <select {...input} placeholder={placeholder}>
      <option></option>
      <option value="0">Lunes</option>
      <option value="1">Martes</option>
      <option value="2">Miércoles</option>
      <option value="3">Jueves</option>
      <option value="4">Viernes</option>
      <option value="5">Sábado</option>
      <option value="6">Domingo</option>
    </select>
    {touched && <div className={`text-danger ${styles.error}`}>{error}
}

);

const required = value => value ? undefined : 'no puede estar en blanco';

const validate = values => {
  const errors = {};

  if (!values.name) {
    errors.name = required(values.name);
  }

  if (!values.delivery) {
    errors.delivery = required(values.delivery);
  }

  if (!values.confirmation) {
    errors.confirmation = required(values.confirmation);
  }

  return errors;
};

class CreateGroupForm extends Component {
  static propTypes = {
    handleSubmit: PropTypes.func.isRequired,
    stopSubmit: PropTypes.func.isRequired,
    errors: PropTypes.object,
    submitting: PropTypes.bool,
  }

  constructor(props) {
    super(props);
  }

  render() {
    const { handleSubmit, submitting } = this.props;

    return (
      <form onSubmit={handleSubmit}>
        <Field
          name="name"
          component={renderInputField}
          placeholder="Elige un nombre para tu grupo de compra"
          label="Nombre del grupo"
        />
        <Field
          name="confirmation"
          component={renderSelectField}
          label="Día de confirmación"
          placeholder="Especifica el día de confirmación de la compra"
        />
        <Field
          name="delivery"
          component={renderSelectField}
          label="Día de entrega"
          placeholder="Especifica el día de entrega de la compra"
        />
        <Button
          type="submit"
          primary
          disabled={submitting}
        >Crear grupo</Button>
      </form>
    );
  }
}

const reduxFormProps = {
  form: CREATE_GROUP_FORM,
  validate
};

const mapStateToProps = (state) => {
  const { form: allForms, groupsReducer: { errors } } = state;

  const form = allForms[CREATE_GROUP_FORM];

  const newState = { errors };

  if (!form) return newState;

  return { ...newState, submitting: form.submitting };
};

export default compose(
  reduxForm(reduxFormProps),
  connect(mapStateToProps, { stopSubmit })
)(CreateGroupForm);
<|endoftext|>


<commit_before>import React from "react";
import uuid from "uuid";

const sounds = {};

if (!window.audioContext) {
  window.audioContext = new (window.AudioContext ||
    window.webkitAudioContext)();
}

function copyToChannel(destination, source, channelNumber) {
  var nowBuffering = destination.getChannelData(channelNumber);
  for (let i = 0; i < source.length; i++) {
    nowBuffering[i] = source[i];
  }
  return destination;
}

function downMixBuffer(buffer, channel) {
  let buff;
  if (buffer.numberOfChannels === 1) {
    buff = window.audioContext.createBuffer(
      window.audioContext.destination.channelCount,
      buffer.duration * window.audioContext.sampleRate,
      window.audioContext.sampleRate
    );
    for (let c = 0; c < channel.length; c++) {
      if (typeof channel[c] === "object") {
        //If there is an array within the channel array, then it is
        //assumed that the values of the array correspond to LR channels
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c][0]);
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c][1]);
      } else {
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c]);
      }
    }
  } else {
    //Do some downmixing to stereo
    buff = window.audioContext.createBuffer(
      window.audioContext.destination.channelCount,
      buffer.duration * window.audioContext.sampleRate,
      window.audioContext.sampleRate
    );

    for (let c = 0; c < channel.length; c++) {
      if (typeof channel[c] === "object") {
        //If there is an array within the channel array, then it is
        //assumed that the values of the array correspond to LR channels
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c][0]);
        buff = copyToChannel(buff, buffer.getChannelData(1), channel[c][1]);
      } else {
        //Combine the two buffer channels into one.
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c]);
      }
    }
  }
  return buff;
}

function playSound(opts) {
  removeSound(opts.id);

  const volume = opts.muted ? 0 : opts.volume || 1;
  const playbackRate = opts.paused ? 0 : opts.playbackRate || 1;
  const channel = opts.channel || [0, 1];
  const asset = opts.url;
  if (!asset) return;
  fetch(asset)
    .then(res => res.arrayBuffer())
    .then(arrayBuffer => {
      window.audioContext.destination.channelCount =
        window.audioContext.destination.maxChannelCount;
      // Connect the sound source to the volume control.
      // Create a buffer from the response ArrayBuffer.
      window.audioContext.decodeAudioData(
        arrayBuffer,
        buffer => {
          const sound = opts || {};
          //Create a new buffer and set it to the specified channel.
          sound.source = window.audioContext.createBufferSource();
          sound.source.buffer = downMixBuffer(buffer, channel);
          sound.source.loop = opts.looping || false;
          sound.source.playbackRate.value = playbackRate;
          sound.volume = window.audioContext.createGain();
          sound.volume.gain.value = volume;
          sound.source.connect(sound.volume);

          sound.source.onended = () => {
            removeSound(opts.id);
            opts.onFinishedPlaying && opts.onFinishedPlaying();
          };
          sound.source.connect(window.audioContext.destination);
          sound.source.start();
          sounds[opts.id || uuid.v4()] = sound;
        },
        function onFailure() {
          console.error("Decoding the audio buffer failed");
        }
      );
    });
}

function removeSound(id) {
  const sound = sounds[id];
  if (sound) {
    sound.stop();
    delete sounds[id];
  }
}

/*componentDidUpdate(prevProps) {
    const withSound = sound => {
      if (!sound) {
        return;
      }

      if (this.props.playStatus === playStatuses.PLAYING) {
        sound.start();
      } else if (this.props.playStatus === playStatuses.STOPPED) {
        sound.stop();
      }

      if (this.props.volume !== prevProps.volume) {
        sound.setVolume(this.props.volume);
      }
      if (this.props.looping !== prevProps.looping) {
        sound.loop = this.props.looping;
      }
      if (this.props.playrate !== prevProps.playrate) {
        sound.playrate.value = this.props.playrate;
      }
    };
    if (this.props.url !== prevProps.url) {
      this.playSound(this.props);
    } else {
      withSound(this.sound);
    }
  }*/

const withSound = Comp => {
  return props => <Comp {...props} playSound={playSound} />;
};

export default withSound;
<commit_msg>Fix a couple of bugs<commit_after>import React from "react";
import uuid from "uuid";

const sounds = {};

if (!window.audioContext) {
  window.audioContext = new (window.AudioContext ||
    window.webkitAudioContext)();
}

function copyToChannel(destination, source, channelNumber) {
  var nowBuffering = destination.getChannelData(channelNumber);
  for (let i = 0; i < source.length; i++) {
    nowBuffering[i] = source[i];
  }
  return destination;
}

function downMixBuffer(buffer, channel) {
  let buff;
  if (buffer.numberOfChannels === 1) {
    buff = window.audioContext.createBuffer(
      window.audioContext.destination.channelCount,
      buffer.duration * window.audioContext.sampleRate,
      window.audioContext.sampleRate
    );
    for (let c = 0; c < channel.length; c++) {
      if (typeof channel[c] === "object") {
        //If there is an array within the channel array, then it is
        //assumed that the values of the array correspond to LR channels
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c][0]);
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c][1]);
      } else {
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c]);
      }
    }
  } else {
    //Do some downmixing to stereo
    buff = window.audioContext.createBuffer(
      window.audioContext.destination.channelCount,
      buffer.duration * window.audioContext.sampleRate,
      window.audioContext.sampleRate
    );

    for (let c = 0; c < channel.length; c++) {
      if (typeof channel[c] === "object") {
        //If there is an array within the channel array, then it is
        //assumed that the values of the array correspond to LR channels
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c][0]);
        buff = copyToChannel(buff, buffer.getChannelData(1), channel[c][1]);
      } else {
        //Combine the two buffer channels into one.
        buff = copyToChannel(buff, buffer.getChannelData(0), channel[c]);
      }
    }
  }
  return buff;
}

function playSound(opts) {
  removeSound(opts.id);
  opts.id = uuid.v4();
  const volume = opts.muted ? 0 : opts.volume || 1;
  const playbackRate = opts.paused ? 0 : opts.playbackRate || 1;
  const channel = opts.channel || [0, 1];
  const asset = opts.url;
  if (!asset) return;
  fetch(asset)
    .then(res => res.arrayBuffer())
    .then(arrayBuffer => {
      window.audioContext.destination.channelCount =
        window.audioContext.destination.maxChannelCount;
      // Connect the sound source to the volume control.
      // Create a buffer from the response ArrayBuffer.
      window.audioContext.decodeAudioData(
        arrayBuffer,
        buffer => {
          const sound = opts || {};
          //Create a new buffer and set it to the specified channel.
          sound.source = window.audioContext.createBufferSource();
          sound.source.buffer = downMixBuffer(buffer, channel);
          sound.source.loop = opts.looping || false;
          sound.source.playbackRate.value = playbackRate;
          sound.volume = window.audioContext.createGain();
          sound.volume.gain.value = volume;
          sound.source.connect(sound.volume);

          sound.source.onended = () => {
            removeSound(opts.id);
            opts.onFinishedPlaying && opts.onFinishedPlaying();
          };
          sound.source.connect(window.audioContext.destination);
          sound.source.start();
          sounds[opts.id] = sound;
        },
        function onFailure() {
          console.error("Decoding the audio buffer failed");
        }
      );
    });
}

function removeSound(id) {
  const sound = sounds[id];
  if (sound) {
    sound.source.stop();
    delete sounds[id];
  }
}

/*componentDidUpdate(prevProps) {
    const withSound = sound => {
      if (!sound) {
        return;
      }

      if (this.props.playStatus === playStatuses.PLAYING) {
        sound.start();
      } else if (this.props.playStatus === playStatuses.STOPPED) {
        sound.stop();
      }

      if (this.props.volume !== prevProps.volume) {
        sound.setVolume(this.props.volume);
      }
      if (this.props.looping !== prevProps.looping) {
        sound.loop = this.props.looping;
      }
      if (this.props.playrate !== prevProps.playrate) {
        sound.playrate.value = this.props.playrate;
      }
    };
    if (this.props.url !== prevProps.url) {
      this.playSound(this.props);
    } else {
      withSound(this.sound);
    }
  }*/

const withSound = Comp => {
  return props => <Comp {...props} playSound={playSound} />;
};

export default withSound;
<|endoftext|>


<commit_before><commit_msg>add debounce to reCaptcha component (#4513)<commit_after><|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';

import css from '../../styles/styles.scss';

class ServerStatus extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      status: 'grey',
      interval: 60000,
    };
    this.loadStatus = this.loadStatus.bind(this);
  }

  componentDidMount() {
    this.loadStatus();
    setInterval(this.loadStatus, this.state.interval);
  }

  updateState(response) {
    let interval = 0;
    switch (response.data.status) {
      case 'yellow':
        interval = 30000;
        break;
      case 'red':
        interval = 15000;
        break;
      default:
        interval = 60000;
        break;
    }
    this.setState({
      status: response.data.status,
      interval,
    });
  }

  loadStatus() {
    axios.get(`https://api.moosecraft.us/api/server/status/${this.props.server}`)
    .catch(({ error }) => console.log(error))
    .then(response => this.updateState(response));
  }

  render() {
    switch (this.state.status) {
      case 'green':
        return (

<button>{this.props.server}</button>

        );
      case 'yellow':
        return (

<button>{this.props.server}</button>

        );
      case 'red':
        return (

<button>{this.props.server}</button>

        );
      default:
        return (

<button>{this.props.server}</button>

        );
    }
  }
}

ServerStatus.propTypes = {
  server: PropTypes.string.isRequired,
};

export default ServerStatus;
<commit_msg>clear the interval on component unmount<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';

import css from '../../styles/styles.scss';

class ServerStatus extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      status: 'grey',
      interval: 60000,
    };
    this.loadStatus = this.loadStatus.bind(this);
  }

  componentDidMount() {
    this.loadStatus();
    this.timeout = setInterval(this.loadStatus, this.state.interval);
  }

  componentWillUnmount() {
    clearInterval(this.timeout);
  }

  updateState(response) {
    let interval = 0;
    switch (response.data.status) {
      case 'yellow':
        interval = 30000;
        break;
      case 'red':
        interval = 15000;
        break;
      default:
        interval = 60000;
        break;
    }
    this.setState({
      status: response.data.status,
      interval,
    });
  }

  loadStatus() {
    axios.get(`https://api.moosecraft.us/api/server/status/${this.props.server}`)
    .catch(({ error }) => console.log(error))
    .then(response => this.updateState(response));
  }

  render() {
    switch (this.state.status) {
      case 'green':
        return (

<button>{this.props.server}</button>

        );
      case 'yellow':
        return (

<button>{this.props.server}</button>

        );
      case 'red':
        return (

<button>{this.props.server}</button>

        );
      default:
        return (

<button>{this.props.server}</button>

        );
    }
  }
}

ServerStatus.propTypes = {
  server: PropTypes.string.isRequired,
};

export default ServerStatus;
<|endoftext|>


<commit_before>import _ from 'lodash';
import {OrderedMap} from 'immutable';

export default class BookService {
    constructor(db) {
        // maybe not needed?
        this.db = db;
    }

    setConnection(connection) {
        this.connection = connection;
    }

    createBook(book, callback) {
        this.connection.query(
            `INSERT INTO
                book (title, language_id, page_count, is_read, started_reading, finished_reading, price)
            VALUES
                (:title, :language, :pageCount, :isRead, :startedReading, :finishedReading, :price)`,
            {
                title: book.title,
                language: book.language,
                pageCount: book.pageCount,
                price: book.price,
                isRead: book.isRead,
                startedReading: book.startedReading,
                finishedReading: book.finishedReading
            },
            callback
        );
    }

    updateBook(id, book, callback) {
        this.connection.query(
            `UPDATE
                book
            SET
                title = :title,
                language_id = :language_id,
                page_count = :page_count,
                is_read = :is_read,
                started_reading = :started_reading,
                finished_reading = :finished_reading,
                price = :price
            WHERE
                id = :id`,
            {
                title: book.title,
                language_id: book.language,
                page_count: book.pageCount,
                is_read: book.isRead,
                started_reading: book.startedReading,
                finished_reading: book.finishedReading,
                price: book.price,
                id: id
            },
            callback
        );
    }

    addAuthors(bookId, authors, callback) {

        let params = {};
        let placeholders = "";

        authors.map((authorId, i) => {
            let bookParam = "bookId" + i;
            let authorParam = "authorId" + i;

            placeholders += "(:" + bookParam + ", :" + authorParam + "),";

            params[bookParam] = bookId;
            params[authorParam] = authorId;
        });

        let placeHolders = _.trimRight(placeholders, ',');
        this.connection.query(

            `INSERT INTO book_author (book_id, author_id) VALUES ${placeHolders}`,
            params,
            callback
        );
    }

    setAuthors(id, authors, callback) {
        let self = this;

        this.removeAuthors(id, function(err, result) {
            if (err) {
                throw err;
            }

            self.addAuthors(id, authors, callback);
        });
    }

    removeAuthors(id, callback) {
        this.connection.query(
            `DELETE ba FROM book_author AS ba WHERE ba.book_id = :id`,
            {id: id},
            callback
        );
    }

    addGenres(bookId, genres, callback) {
        let params = {};
        let placeholders = "";

        genres.map((genreId, i) => {
            let bookParam = "bookId" + i;
            let genreParam = "genreId" + i;

            placeholders += "(:" + bookParam + ", :" + genreParam + ", 'book'),";

            params[bookParam] = bookId;
            params[genreParam] = genreId;
        });

        let placeHolders = _.trimRight(placeholders, ',');
        this.connection.query(

            `INSERT INTO xi_tagging (resource_id, tag_id, resource_type) VALUES ${placeHolders}`,
            params,
            callback
        );
    }

    setGenres(id, genres, callback) {

        this.removeGenres(id, (err, result) => {
            if (err) {
                throw err;
            }

            this.addGenres(id, genres, callback);
        });
    }

    removeGenres(bookId, callback) {
        this.connection.query(
            `DELETE bg FROM xi_tagging AS bg WHERE bg.resource_id = :bookId`,
            {bookId: bookId},
            callback
        );
    }

    getBook(id, callback) {
        this.connection.query(
            `SELECT
                a.id AS author_id,
                a.firstname,
                a.lastname,
                CONCAT(a.firstname, ' ', a.lastname) AS author_name,
                b.id,
                b.title,
                b.language_id,
                b.page_count,
                b.is_read,
                b.isbn,
                b.created_at,
                b.updated_at,
                b.started_reading,
                b.finished_reading,
                b.rating,
                b.price,
                g.id AS genre_id,
                g.name AS genre_name
            FROM
                book AS b LEFT JOIN book_author AS ba ON b.id = ba.book_id
                LEFT JOIN author AS a ON a.id = ba.author_id
                LEFT JOIN xi_tagging AS bg ON b.id = bg.resource_id
                LEFT JOIN xi_tag AS g ON g.id = bg.tag_id
            WHERE
                b.id = :id`,
            {id: id},
            callback
        );
    }

    getBooks(mode, callback) {
        switch (mode) {
            case 'read':
                this.getReadBooks(callback);
                break;
            case 'unread':
                this.getUnreadBooks(callback);
                break;
            default:
                this.getAllBooks(callback);
                break;
        }
    }

    getAllBooks(callback) {
        this.connection.query(
            this.createGetBooksQuery(),
            callback
        );
    }

    getReadBooks(callback) {
        let query = this.createGetBooksQuery(true);

        this.connection.query(
            query,
            callback
        );
    }

    getUnreadBooks(callback) {
        let query = this.createGetBooksQuery(false);

        this.connection.query(
            query,
            callback
        );
    }

    createGetBooksQuery(isRead = null) {
        let query = `SELECT
                b.id,
                b.title,
                b.language_id,
                b.page_count,
                b.is_read,
                b.isbn,
                b.created_at,
                b.updated_at,
                b.started_reading,
                b.finished_reading,
                b.rating,
                b.price,
                a.firstname,
                a.lastname,
                CONCAT(firstname, ' ', lastname) AS author_name
        FROM
            book AS b
            LEFT JOIN book_author AS ba ON ba.book_id = b.id
            LEFT JOIN author AS a ON ba.author_id = a.id
        `;

        if (null !== isRead) {
            if(isRead) {
                query += ' WHERE b.is_read = 1';
            } else {
                query += ' WHERE b.is_read != 1';
            }
        }

        query += ' ORDER BY b.title ASC';

        return query;
    }

    createBookObject(result) {
        if (result.length == 0) {
            return null;
        }

        let authors = OrderedMap();
        let genres = OrderedMap();
        let book = null;

        result.map(row => {
            if (null == book) {
                book = {
                    id: row.id,
                    title: row.title,
                    language_id: row.language_id,
                    page_count: row.page_count,
                    is_read: row.is_read,
                    started_reading: row.started_reading,
                    finished_reading: row.finished_reading,
                    price: row.price
                };
            }

            authors = authors.set(row.author_id, {
                id: row.author_id,
                firstname: row.firstname,
                lastname: row.lastname,
                name: row.author_name
            });

            if (null != row.genre_id) {
                genres = genres.set(row.genre_id, {
                    id: row.genre_id,
                    name: row.genre_name
                });
            }
        });

        book.authors = authors.toArray();
        book.genres = genres.toArray();

        return book;
    }
};
<commit_msg>trimRight -> trimEnd<commit_after>import _ from 'lodash';
import {OrderedMap} from 'immutable';

export default class BookService {
    constructor(db) {
        // maybe not needed?
        this.db = db;
    }

    setConnection(connection) {
        this.connection = connection;
    }

    createBook(book, callback) {
        this.connection.query(
            `INSERT INTO
                book (title, language_id, page_count, is_read, started_reading, finished_reading, price)
            VALUES
                (:title, :language, :pageCount, :isRead, :startedReading, :finishedReading, :price)`,
            {
                title: book.title,
                language: book.language,
                pageCount: book.pageCount,
                price: book.price,
                isRead: book.isRead,
                startedReading: book.startedReading,
                finishedReading: book.finishedReading
            },
            callback
        );
    }

    updateBook(id, book, callback) {
        this.connection.query(
            `UPDATE
                book
            SET
                title = :title,
                language_id = :language_id,
                page_count = :page_count,
                is_read = :is_read,
                started_reading = :started_reading,
                finished_reading = :finished_reading,
                price = :price
            WHERE
                id = :id`,
            {
                title: book.title,
                language_id: book.language,
                page_count: book.pageCount,
                is_read: book.isRead,
                started_reading: book.startedReading,
                finished_reading: book.finishedReading,
                price: book.price,
                id: id
            },
            callback
        );
    }

    addAuthors(bookId, authors, callback) {

        let params = {};
        let placeholders = "";

        authors.map((authorId, i) => {
            let bookParam = "bookId" + i;
            let authorParam = "authorId" + i;

            placeholders += "(:" + bookParam + ", :" + authorParam + "),";

            params[bookParam] = bookId;
            params[authorParam] = authorId;
        });

        let placeHolders = _.trimEnd(placeholders, ',');
        this.connection.query(

            `INSERT INTO book_author (book_id, author_id) VALUES ${placeHolders}`,
            params,
            callback
        );
    }

    setAuthors(id, authors, callback) {
        let self = this;

        this.removeAuthors(id, function(err, result) {
            if (err) {
                throw err;
            }

            self.addAuthors(id, authors, callback);
        });
    }

    removeAuthors(id, callback) {
        this.connection.query(
            `DELETE ba FROM book_author AS ba WHERE ba.book_id = :id`,
            {id: id},
            callback
        );
    }

    addGenres(bookId, genres, callback) {
        let params = {};
        let placeholders = "";

        genres.map((genreId, i) => {
            let bookParam = "bookId" + i;
            let genreParam = "genreId" + i;

            placeholders += "(:" + bookParam + ", :" + genreParam + ", 'book'),";

            params[bookParam] = bookId;
            params[genreParam] = genreId;
        });

        let placeHolders = _.trimEnd(placeholders, ',');
        this.connection.query(

            `INSERT INTO xi_tagging (resource_id, tag_id, resource_type) VALUES ${placeHolders}`,
            params,
            callback
        );
    }

    setGenres(id, genres, callback) {

        this.removeGenres(id, (err, result) => {
            if (err) {
                throw err;
            }

            this.addGenres(id, genres, callback);
        });
    }

    removeGenres(bookId, callback) {
        this.connection.query(
            `DELETE bg FROM xi_tagging AS bg WHERE bg.resource_id = :bookId`,
            {bookId: bookId},
            callback
        );
    }

    getBook(id, callback) {
        this.connection.query(
            `SELECT
                a.id AS author_id,
                a.firstname,
                a.lastname,
                CONCAT(a.firstname, ' ', a.lastname) AS author_name,
                b.id,
                b.title,
                b.language_id,
                b.page_count,
                b.is_read,
                b.isbn,
                b.created_at,
                b.updated_at,
                b.started_reading,
                b.finished_reading,
                b.rating,
                b.price,
                g.id AS genre_id,
                g.name AS genre_name
            FROM
                book AS b LEFT JOIN book_author AS ba ON b.id = ba.book_id
                LEFT JOIN author AS a ON a.id = ba.author_id
                LEFT JOIN xi_tagging AS bg ON b.id = bg.resource_id
                LEFT JOIN xi_tag AS g ON g.id = bg.tag_id
            WHERE
                b.id = :id`,
            {id: id},
            callback
        );
    }

    getBooks(mode, callback) {
        switch (mode) {
            case 'read':
                this.getReadBooks(callback);
                break;
            case 'unread':
                this.getUnreadBooks(callback);
                break;
            default:
                this.getAllBooks(callback);
                break;
        }
    }

    getAllBooks(callback) {
        this.connection.query(
            this.createGetBooksQuery(),
            callback
        );
    }

    getReadBooks(callback) {
        let query = this.createGetBooksQuery(true);

        this.connection.query(
            query,
            callback
        );
    }

    getUnreadBooks(callback) {
        let query = this.createGetBooksQuery(false);

        this.connection.query(
            query,
            callback
        );
    }

    createGetBooksQuery(isRead = null) {
        let query = `SELECT
                b.id,
                b.title,
                b.language_id,
                b.page_count,
                b.is_read,
                b.isbn,
                b.created_at,
                b.updated_at,
                b.started_reading,
                b.finished_reading,
                b.rating,
                b.price,
                a.firstname,
                a.lastname,
                CONCAT(firstname, ' ', lastname) AS author_name
        FROM
            book AS b
            LEFT JOIN book_author AS ba ON ba.book_id = b.id
            LEFT JOIN author AS a ON ba.author_id = a.id
        `;

        if (null !== isRead) {
            if(isRead) {
                query += ' WHERE b.is_read = 1';
            } else {
                query += ' WHERE b.is_read != 1';
            }
        }

        query += ' ORDER BY b.title ASC';

        return query;
    }

    createBookObject(result) {
        if (result.length == 0) {
            return null;
        }

        let authors = OrderedMap();
        let genres = OrderedMap();
        let book = null;

        result.map(row => {
            if (null == book) {
                book = {
                    id: row.id,
                    title: row.title,
                    language_id: row.language_id,
                    page_count: row.page_count,
                    is_read: row.is_read,
                    started_reading: row.started_reading,
                    finished_reading: row.finished_reading,
                    price: row.price
                };
            }

            authors = authors.set(row.author_id, {
                id: row.author_id,
                firstname: row.firstname,
                lastname: row.lastname,
                name: row.author_name
            });

            if (null != row.genre_id) {
                genres = genres.set(row.genre_id, {
                    id: row.genre_id,
                    name: row.genre_name
                });
            }
        });

        book.authors = authors.toArray();
        book.genres = genres.toArray();

        return book;
    }
};
<|endoftext|>


<commit_before>import $ from 'jquery';
import MouseTrap from 'mousetrap';
import 'jquery-ui/widgets/slider';

import Signal from '../../utils/signal';
import { state } from '../../state';
import { song } from '../../utils/songmanager';
import { player } from '../../audio/player';

import transportTemplate from './templates/transport.marko';

import modfile from '../../../data/onward.xm';

import styles from './styles.css';

export default class Transport {
  constructor(target) {
    this.target = target;
    this.lastTransport = undefined;

    MouseTrap.bind(["{", "}"], (e) => {
      state.set({
        transport: {
          step: e.key == "{" ? Math.max(0, state.transport.get("step") - 1) :
                               state.transport.get("step") + 1,
        },
      });
      e.preventDefault();
    });

    MouseTrap.bind(["\"", "|"], (e) => {
      state.set({
        transport: {
          octave: e.key == "\"" ? Math.max(0, state.transport.get("octave") - 1) :
                                  state.transport.get("octave") + 1,
        },
      });
      e.preventDefault();
    });

    Signal.connect(state, "transportChanged", this, "onTransportChanged");
    Signal.connect(song, "songChanged", this, "onSongChanged");
  }

  render() {
    $(this.target).append(transportTemplate.renderToString({transport: state.transport.toJS(), song: song.song}));

    $(this.target).find("#master-volume").slider({
      max: 1.0,
      min: 0.0,
      range: "min",
      step: 0.01,
      value: player.gainNode.gain.value,
      slide: (e, ui) => {
        player.gainNode.gain.value = ui.value;
      },
    });

    $(this.target).find('input').bind("enterKey", (e) => {
      state.set({
        transport: {
          octave: parseInt($(this.target).find("#octave").val()),
        },
      });
      song.setBPM(parseInt($(this.target).find("#bpm").val()));
      song.setSpeed(parseInt($(this.target).find("#speed").val()));
      $(e.target).blur();
    });
    $(this.target).find('input').keyup(function(e){
      if(e.keyCode == 13)
      {
        $(this).trigger("enterKey");
      }
    });
    $(this.target).find('#play').click((e) => {
      player.play();
    });
    $(this.target).find('#play-pattern').click((e) => {
      player.playPattern(state.cursor.get("pattern"));
    });
    $(this.target).find('#pause').click((e) => {
      player.pause();
    });
    $(this.target).find('#stop').click((e) => {
      player.stop();
    });
    $(this.target).find('#reset').click((e) => {
      player.reset();
    });
    $(this.target).find('#new').click((e) => {
      song.newSong();
    });
    $(this.target).find('#load').click((e) => {
      $( "#dialog" ).empty();
      $( "#dialog" ).append($("<input type=\"file\" id=\"file-input\" />"));
      $( "#dialog" ).dialog({
        width: 500,
        modal: true,
        buttons: {
          Ok: function() {
            var files = $("#file-input")[0].files;
            if (files.length > 0) {
              song.loadSongFromFile(files[0], (result) => {
                song.setSong(result);
              });
            }
            $( this ).dialog( "close" );
          },
          Cancel: function() {
            $( this ).dialog( "close" );
          },
          Demo: function() {
            song.downloadSong(modfile);
            $( this ).dialog( "close" );
          }
        }
      });
    });
    $(this.target).find('#save').click((e) => {
      song.saveSongToLocal();
    });
  }

  onTransportChanged() {
    if (this.lastTransport !== state.transport) {
      $(this.target).find("#octave").val(state.transport.get("octave"));
      $(this.target).find("#bpm").val(state.transport.get("bpm"));
      $(this.target).find("#speed").val(state.transport.get("speed"));

      this.lastTransport = state.transport;
    }
  }

  refresh() {
    $(this.target).empty();
    this.render();
  }

  onSongChanged() {
    this.refresh();
  }
}
<commit_msg>Add calls to player.stop in transport.<commit_after>import $ from 'jquery';
import MouseTrap from 'mousetrap';
import 'jquery-ui/widgets/slider';

import Signal from '../../utils/signal';
import { state } from '../../state';
import { song } from '../../utils/songmanager';
import { player } from '../../audio/player';

import transportTemplate from './templates/transport.marko';

import modfile from '../../../data/onward.xm';

import styles from './styles.css';

export default class Transport {
  constructor(target) {
    this.target = target;
    this.lastTransport = undefined;

    MouseTrap.bind(["{", "}"], (e) => {
      state.set({
        transport: {
          step: e.key == "{" ? Math.max(0, state.transport.get("step") - 1) :
                               state.transport.get("step") + 1,
        },
      });
      e.preventDefault();
    });

    MouseTrap.bind(["\"", "|"], (e) => {
      state.set({
        transport: {
          octave: e.key == "\"" ? Math.max(0, state.transport.get("octave") - 1) :
                                  state.transport.get("octave") + 1,
        },
      });
      e.preventDefault();
    });

    Signal.connect(state, "transportChanged", this, "onTransportChanged");
    Signal.connect(song, "songChanged", this, "onSongChanged");
  }

  render() {
    $(this.target).append(transportTemplate.renderToString({transport: state.transport.toJS(), song: song.song}));

    $(this.target).find("#master-volume").slider({
      max: 1.0,
      min: 0.0,
      range: "min",
      step: 0.01,
      value: player.gainNode.gain.value,
      slide: (e, ui) => {
        player.gainNode.gain.value = ui.value;
      },
    });

    $(this.target).find('input').bind("enterKey", (e) => {
      state.set({
        transport: {
          octave: parseInt($(this.target).find("#octave").val()),
        },
      });
      song.setBPM(parseInt($(this.target).find("#bpm").val()));
      song.setSpeed(parseInt($(this.target).find("#speed").val()));
      $(e.target).blur();
    });
    $(this.target).find('input').keyup(function(e){
      if(e.keyCode == 13)
      {
        $(this).trigger("enterKey");
      }
    });
    $(this.target).find('#play').click((e) => {
      player.play();
    });
    $(this.target).find('#play-pattern').click((e) => {
      player.playPattern(state.cursor.get("pattern"));
    });
    $(this.target).find('#pause').click((e) => {
      player.pause();
    });
    $(this.target).find('#stop').click((e) => {
      player.stop();
    });
    $(this.target).find('#reset').click((e) => {
      player.stop();
      player.reset();
    });
    $(this.target).find('#new').click((e) => {
      player.stop();
      song.newSong();
    });
    $(this.target).find('#load').click((e) => {
      $( "#dialog" ).empty();
      $( "#dialog" ).append($("<input type=\"file\" id=\"file-input\" />"));
      $( "#dialog" ).dialog({
        width: 500,
        modal: true,
        buttons: {
          Ok: function() {
            var files = $("#file-input")[0].files;
            if (files.length > 0) {
              song.loadSongFromFile(files[0], (result) => {
                song.setSong(result);
              });
            }
            $( this ).dialog( "close" );
          },
          Cancel: function() {
            $( this ).dialog( "close" );
          },
          Demo: function() {
            player.stop();
            song.downloadSong(modfile);
            $( this ).dialog( "close" );
          }
        }
      });
    });
    $(this.target).find('#save').click((e) => {
      song.saveSongToLocal();
    });
  }

  onTransportChanged() {
    if (this.lastTransport !== state.transport) {
      $(this.target).find("#octave").val(state.transport.get("octave"));
      $(this.target).find("#bpm").val(state.transport.get("bpm"));
      $(this.target).find("#speed").val(state.transport.get("speed"));

      this.lastTransport = state.transport;
    }
  }

  refresh() {
    $(this.target).empty();
    this.render();
  }

  onSongChanged() {
    this.refresh();
  }
}
<|endoftext|>


<commit_before>(function(context, $) {

// constructor
var Muster = function(args) {
  if (args) {
    this.url = args.url;
    this.database = args.database;
  }
};

// Constructor wrapper (always return an object; never a function. `new`
// keyword is optional.)
var init = function(args) {
  return new Muster(args);
};

// expose Muster to context (i.e. window.Muster)
context.Muster = init;

Muster.prototype = {

  query: function(query, callback) {
    var muster = this;
    $.getJSON(getQueryString(this.url, this.database, query), function(data) {
      muster.columns = data.columns;
      muster.results = data.results;
      callback.apply(muster);
    });
  },

  isEmpty: function() {
    return this.results.length < 1;
  },

  clone: function() {
    var oldMuster = this;
    var newMuster = init();
    for (attr in oldMuster) {
      newMuster[attr] = oldMuster[attr];
    }
    return newMuster;
  },

  filter: function(column, value) {
    var column = arguments[0];
    var value = arguments[1];
    var filteredResults = $.grep(this.results, function(row, i) {
      return row[column] == value;
    });
    var clone = this.clone();
    clone.results = filteredResults;
    return clone;
  },

  get: function(column) {
    var ret = [];
    $.each(this.results, function(k, row) {
      ret.push(row[column]);
    });
    return ret;
  },

  getUnique: function(column) {
    return $.unique(this.get(column));
  },

  getFirst: function(column) {
    return this.results[0][column];
  },

  groupBy: function(column) {

    // ret is an array of arrays. Each array in ret shares the same value for
    // row[column]. uniq keeps track of whether we've encountered a value
    // before so we only traverse the results once.
    var ret = [],
        uniq = [],
        muster = this;

    $.each(this.results, function(k, row) {
      var i = uniq.indexOf(row[column]);
      if (i < 0) {
        uniq.push(row[column]);
        i = uniq.length - 1;
        ret[i] = muster.clone();
        ret[i].results = [];
      }
      ret[i].results.push(row);
    });
    return ret;
  },

  // TODO comment this and maybe refactor. Using .groupBy then iterating over
  // the list again is not the most efficient technique possible, but, again,
  // performance vs. readability... It seems pretty fast.
  serializeJoinedResults: function(uniqueColumn) {
    var results = [];
    var m = this; // for use in inner functions
    var grouped = m.groupBy(uniqueColumn);
    var columns = grouped[0].columns;
    columns.splice(grouped[0].columns.indexOf(uniqueColumn), 1);
    $.each(grouped, function(k, group) {
      var mergedRow = {};
      $.each(group.results, function(k, row) {
        $.each(columns, function(k, column) {
          if (mergedRow[column] == undefined) {
            mergedRow[column] = row[column];
          }
          else if (typeof mergedRow[column] == 'string') {
            if (mergedRow[column] != row[column]) {
              var val = mergedRow[column];
              mergedRow[column] = [row[column]];
            }
          }
          else {
            mergedRow[column].push(row[column]);
          }
        });
      });
      results.push(mergedRow);
    });
    var clone = this.clone();
    clone.results = results;
    return clone;
  },

  toTable: function(columnSpec) {

    var columns, columnLabels;

    if (!columnSpec) {
      columns = columnLabels = this.columns;
    }
    else {
      columns = [], columnLabels = [];
      $.each(columnSpec, function(key, column) {
        columns.push(column[0]);
        columnLabels.push(column[1]);
      });
    }

    var table = $('

');
    var thead = table.find('thead tr');
    var tbody = $('
');

    $.each(columnLabels, function(k, columnLabel) {
      thead.append('' + columnLabel);
    });

    $.each(this.results, function(k, row) {
      var tr = $('
');
      table.append(tr);
      $.each(columns, function(k, column) {
        var text;

        // formatting function
        if (typeof column == 'function') {
          text = column.apply(row);
        }
        // multiple values
        else if (row[column] instanceof Array) {
          text = row[column].join('

');
          text = '

' + text + '

';
        }
        // just a string
        else {
          text = row[column];
        }
        tr.append('' + text);
      });
    });
    return sortablize(table);
  }
};

// Assemble the request URI
function getQueryString(url, database, params) {

  // Add database to parameters
  params['database'] = database;

  // assemble the parameters
  var parameterPairs = [];
  $.each([
         'database', 'select', 'from', 'where', 'order'
  ], function() {
    if (params[this] != null && params[this].length > 0) {
      parameterPairs.push( [this, escape(params[this])].join('=') );
    }
  });
  parameterPairs.push('callback=?'); // jQuery JSONP support

  return [url, '?', parameterPairs.join('&')].join('');
}

// return a sortable version of the table
function sortablize(table) {
  table.find('th').css({cursor: 'pointer'}).click(function(event) {
    var th = $(event.target);
    var table = th.closest('table');
    var tbody = table.find('tbody');
    var index = th.index() + 1;
    var rows = table.find('tbody tr');
    tbody.append(rows.sort(function(left, right) {

      left  =  $(left).find('td:nth-child(' + index + ')').text().toLowerCase();
      right = $(right).find('td:nth-child(' + index + ')').text().toLowerCase();

      if      (left < right)  return -1;
      else if (left == right) return 0;
      else                    return 1;
    }));
  });
  return table;
}

// Add Array.indexOf to browsers that don't have it (i.e. IE)
(function() {
  if (!Array.indexOf) {
    Array.prototype.indexOf = function(obj) {
      for (var i = 0, len = this.length; i < len; i++) {
        if (this[i] == obj)
          return i;
      }
      return -1;
    };
  }
})();

})(window, jQuery);

<commit_msg>Do #65: stable table sort<commit_after>(function(context, $) {

// constructor
var Muster = function(args) {
  if (args) {
    this.url = args.url;
    this.database = args.database;
  }
};

// Constructor wrapper (always return an object; never a function. `new`
// keyword is optional.)
var init = function(args) {
  return new Muster(args);
};

// expose Muster to context (i.e. window.Muster)
context.Muster = init;

Muster.prototype = {

  query: function(query, callback) {
    var muster = this;
    $.getJSON(getQueryString(this.url, this.database, query), function(data) {
      muster.columns = data.columns;
      muster.results = data.results;
      callback.apply(muster);
    });
  },

  isEmpty: function() {
    return this.results.length < 1;
  },

  clone: function() {
    var oldMuster = this;
    var newMuster = init();
    for (attr in oldMuster) {
      newMuster[attr] = oldMuster[attr];
    }
    return newMuster;
  },

  filter: function(column, value) {
    var column = arguments[0];
    var value = arguments[1];
    var filteredResults = $.grep(this.results, function(row, i) {
      return row[column] == value;
    });
    var clone = this.clone();
    clone.results = filteredResults;
    return clone;
  },

  get: function(column) {
    var ret = [];
    $.each(this.results, function(k, row) {
      ret.push(row[column]);
    });
    return ret;
  },

  getUnique: function(column) {
    return $.unique(this.get(column));
  },

  getFirst: function(column) {
    return this.results[0][column];
  },

  groupBy: function(column) {

    // ret is an array of arrays. Each array in ret shares the same value for
    // row[column]. uniq keeps track of whether we've encountered a value
    // before so we only traverse the results once.
    var ret = [],
        uniq = [],
        muster = this;

    $.each(this.results, function(k, row) {
      var i = uniq.indexOf(row[column]);
      if (i < 0) {
        uniq.push(row[column]);
        i = uniq.length - 1;
        ret[i] = muster.clone();
        ret[i].results = [];
      }
      ret[i].results.push(row);
    });
    return ret;
  },

  // TODO comment this and maybe refactor. Using .groupBy then iterating over
  // the list again is not the most efficient technique possible, but, again,
  // performance vs. readability... It seems pretty fast.
  serializeJoinedResults: function(uniqueColumn) {
    var results = [];
    var m = this; // for use in inner functions
    var grouped = m.groupBy(uniqueColumn);
    var columns = grouped[0].columns;
    columns.splice(grouped[0].columns.indexOf(uniqueColumn), 1);
    $.each(grouped, function(k, group) {
      var mergedRow = {};
      $.each(group.results, function(k, row) {
        $.each(columns, function(k, column) {
          if (mergedRow[column] == undefined) {
            mergedRow[column] = row[column];
          }
          else if (typeof mergedRow[column] == 'string') {
            if (mergedRow[column] != row[column]) {
              var val = mergedRow[column];
              mergedRow[column] = [row[column]];
            }
          }
          else {
            mergedRow[column].push(row[column]);
          }
        });
      });
      results.push(mergedRow);
    });
    var clone = this.clone();
    clone.results = results;
    return clone;
  },

  toTable: function(columnSpec) {

    var columns, columnLabels;

    if (!columnSpec) {
      columns = columnLabels = this.columns;
    }
    else {
      columns = [], columnLabels = [];
      $.each(columnSpec, function(key, column) {
        columns.push(column[0]);
        columnLabels.push(column[1]);
      });
    }

    var table = $('

');
    var thead = table.find('thead tr');
    var tbody = $('
');

    $.each(columnLabels, function(k, columnLabel) {
      thead.append('' + columnLabel);
    });

    $.each(this.results, function(k, row) {
      var tr = $('
');
      table.append(tr);
      $.each(columns, function(k, column) {
        var text;

        // formatting function
        if (typeof column == 'function') {
          text = column.apply(row);
        }
        // multiple values
        else if (row[column] instanceof Array) {
          text = row[column].join('

');
          text = '

' + text + '

';
        }
        // just a string
        else {
          text = row[column];
        }
        tr.append('' + text);
      });
    });
    return sortablize(table);
  }
};

// Assemble the request URI
function getQueryString(url, database, params) {

  // Add database to parameters
  params['database'] = database;

  // assemble the parameters
  var parameterPairs = [];
  $.each([
         'database', 'select', 'from', 'where', 'order'
  ], function() {
    if (params[this] != null && params[this].length > 0) {
      parameterPairs.push( [this, escape(params[this])].join('=') );
    }
  });
  parameterPairs.push('callback=?'); // jQuery JSONP support

  return [url, '?', parameterPairs.join('&')].join('');
}

// return a stable sortable version of the table
function sortablize(table) {
  table.find('th').css({cursor: 'pointer'}).click(function(event) {
    var th = $(event.target);
    var table = th.closest('table');
    var tbody = table.find('tbody');
    var index = th.index() + 1;
    var rows = table.find('tbody tr');
    tbody.append(rows.msort(function(left, right) {

      left  =  $(left).find('td:nth-child(' + index + ')').text().toLowerCase();
      right = $(right).find('td:nth-child(' + index + ')').text().toLowerCase();

      if      (left < right)  return -1;
      else if (left == right) return 0;
      else                    return 1;
    }));
  });
  return table;
}

// Add Array.indexOf to browsers that don't have it (i.e. IE)
(function() {
  if (!Array.indexOf) {
    Array.prototype.indexOf = function(obj) {
      for (var i = 0, len = this.length; i < len; i++) {
        if (this[i] == obj)
          return i;
      }
      return -1;
    };
  }
})();

// Add stable merge sort to Array and jQuery prototypes
(function() {

  Array.prototype.msort = jQuery.fn.msort = msort;

  function msort(compare) {

    var length = this.length,
        middle = Math.floor(length / 2);

    if (!compare) {
      compare = function() {
        return arguments[0] - arguments[1];
      };
    }

    if (length < 2) {
      return this;
    }

    return merge(
      this.slice(0, middle).msort(compare),
      this.slice(middle, length).msort(compare),
      compare
    );
  }

  function merge(left, right, compare) {

    var result = [];

    while (left.length > 0 || right.length > 0) {
      if (left.length > 0 && right.length > 0) {
        if (compare(left[0], right[0]) <= 0) {
          result.push(left[0]);
          left = left.slice(1);
        }
        else {
          result.push(right[0]);
          right = right.slice(1);
        }
      }
      else if (left.length > 0) {
        result.push(left[0]);
        left = left.slice(1);
      }
      else if (right.length > 0) {
        result.push(right[0]);
        right = right.slice(1);
      }
    }
    return result;
  }
})();

})(window, jQuery);

<|endoftext|>


<commit_before>(function() {
  var __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
  module.exports = function(BasePlugin) {
    var GulpPlugin;
    return GulpPlugin = (function(_super) {
      __extends(GulpPlugin, _super);
      GulpPlugin.prototype.name = 'gulp';
      GulpPlugin.prototype.config = {
        writeAfter: [],
        writeBefore: false,
        renderBefore: false,
        renderAfter: false,
        generateBefore: false,
        generateAfter: false,
        populateCollectionsBefore: false,
        populateCollections: false
      };
      function GulpPlugin() {
        GulpPlugin.__super__.constructor.apply(this, arguments);
        this.safeps = require('safeps');
        this.path = require('path');
        this.glob = require('glob');
        this;
      }
      GulpPlugin.prototype.writeBefore = function(opts, next) {
        var tasks;
        if (tasks = this.getConfig().writeBefore || false) {
          this.processGulp(tasks, opts, next);
        } else {
          return next();
        }
        return this;
      };
      GulpPlugin.prototype.writeAfter = function(opts, next) {
        var tasks;
        if (tasks = this.getConfig().writeAfter || false) {
          this.processGulp(tasks, opts, next);
        } else {
          return next();
        }
        return this;
      };
      GulpPlugin.prototype.renderBefore = function(opts, next) {
        var tasks;
        if (tasks = this.getConfig().renderBefore || false) {
          this.processGulp(tasks, opts, next);
        } else {
          return next();
        }
        return this;
      };
      GulpPlugin.prototype.renderAfter = function(opts, next) {
        var tasks;
        if (tasks = this.getConfig().renderAfter || false) {
          this.processGulp(tasks, opts, next);
        } else {
          return next();
        }
        return this;
      };
      GulpPlugin.prototype.generateBefore = function(opts, next) {
        var tasks;
        if (tasks = this.getConfig().generateBefore || false) {
          this.processGulp(tasks, opts, next);
        } else {
          return next();
        }
        return this;
      };

      GulpPlugin.prototype.generateAfter = function(opts, next) {
        var tasks;
        if (tasks = this.getConfig().generateAfter || false) {
          this.processGulp(tasks, opts, next);
        } else {
          return next();
        }
        return this;
      };

      GulpPlugin.prototype.populateCollectionsBefore = function(opts, next) {
        var tasks;
        if (tasks = this.getConfig().populateCollectionsBefore || false) {
          this.processGulp(tasks, opts, next);
        } else {
          return next();
        }
        return this;
      };

      GulpPlugin.prototype.populateCollections = function(opts, next) {
        var tasks;
        if (tasks = this.getConfig().populateCollections || false) {
          this.processGulp(tasks, opts, next);
        } else {
          return next();
        }
        return this;
      };

      GulpPlugin.prototype.processGulp = function(task, opts, next) {
        var command, err, files, gulpPath, rootPath, task, _i, _len, _ref;
        rootPath = this.docpad.getConfig().rootPath;
        files = this.glob.sync('**/gulp/bin/gulp.js', {
          cwd: rootPath,
          nosort: true
        });
        if (gulpPath = files[0] || false) {
          command = [this.path.join(rootPath, gulpPath)];
          command.push(task);
          this.safeps.spawn(command, {
            cwd: rootPath,
            output: true
          }, next);
        } else {
          err = new Error('Could not find the gulp command line interface.');
          return next(err);
          err;
        }
        return this;
      };

      return GulpPlugin;

    })(BasePlugin);
  };

}).call(this);
<commit_msg>remove unnecessary out file<commit_after><|endoftext|>


<commit_before>//The purpose of this module is to deal with autonomous lists.
//If you need lists inside a form please see the listFor helper function in a form.
//The following lists can
//- be loaded from a criteria (or without) (the criteria can be the result of a form)
//- be paginated
//- be displayed in any list container.
let {camelCase, capitalize} = require('lodash/string');
let {types, builder} = require('focus').component;
let actionBuilder = require('focus').list.actionBuilder;
let type = types;
let assign = require('object-assign');

const STORE_NODE = ['criteria', 'groupingKey', 'sortBy', 'sortAsc', 'dataList', 'totalCount'];
const DEFAULT_LIST_COMPONENT = require('../../list/table/list').component;
/**
 * Cretes a name for the property listener.
 * @param  {string} node - Node name.
 * @return {string} the built property.
 */
function _listenerProp(node){
    return `add${capitalize(camelCase(node))}ChangeListener`;
}
/**
 * Mixin to deal the list page.
 * @type {Object}
 */
let listPageMixin = {
    getDefaultProps(){
        return {
            ListComponent: DEFAULT_LIST_COMPONENT,
            pickProps(props){return props;}
        };
    },
    getInitialState(){
        return {};
    },
    /** @inheritdoc */
    propTypes: {
        //Store object.
        pickProps: type('func'),
        service: type('func'),
        store: type('object').isRequired
    },
    /**
     *  Build the action from.
     */
    _buildAction(){
        this._action = this.props.action || actionBuilder({
            service: this.props.service,
            identifier: this.props.store.identifier,
            getListOptions: () => {return this.props.store.getValue.call(this.props.store); } // Binding the store in the function call
        });
    },
    /**
     * Read the state from the store.
     * @return {object} - The object read from the store.
     */
    _getStateFromStore(){
        let store = this.props.store;
        return store.getValue();
    },
    /**
     * Hanlde the list store change.
     */
    _handleStoreChanged(){
        this.setState(this._getStateFromStore());
    },
    /**
     * Register the store nodes.
     */
    _registerStoreNode(){
        STORE_NODE.forEach((node)=>{
            this.props.store[_listenerProp(node)](this._handleStoreChanged)
        });
    },
    /**
     * build the list props.
     * @return {object} - the list property.
     */
    _buildListProps(){
        let {props, state} = this;
        let {dataList, totalCount} = state;
        dataList = dataList || [];
        return assign(props, state, {
            data: dataList,
            fetchNextPage: this._action.load,
            hasMoreData: dataList.length < totalCount
        });
    },
    /** @inheritdoc */
    componentWillMount(){
        this._registerStoreNode();
        this._buildAction();
        this._action.load();
    },
    /** @inheritdoc */
    render(){
        let listProps = this._buildListProps();
        return <this.props.ListComponent {...listProps} />;
    }
};

module.exports = builder(listPageMixin);
<commit_msg>[page] list add a criteria change listener which trigger a search.<commit_after>//The purpose of this module is to deal with autonomous lists.
//If you need lists inside a form please see the listFor helper function in a form.
//The following lists can
//- be loaded from a criteria (or without) (the criteria can be the result of a form)
//- be paginated
//- be displayed in any list container.
let {camelCase, capitalize} = require('lodash/string');
let {types, builder} = require('focus').component;
let actionBuilder = require('focus').list.actionBuilder;
let type = types;
let assign = require('object-assign');

const STORE_NODE = ['criteria', 'groupingKey', 'sortBy', 'sortAsc', 'dataList', 'totalCount'];
const DEFAULT_LIST_COMPONENT = require('../../list/table/list').component;
/**
 * Cretes a name for the property listener.
 * @param  {string} node - Node name.
 * @return {string} the built property.
 */
function _listenerProp(node){
    return `add${capitalize(camelCase(node))}ChangeListener`;
}
/**
 * Mixin to deal the list page.
 * @type {Object}
 */
let listPageMixin = {
    getDefaultProps(){
        return {
            ListComponent: DEFAULT_LIST_COMPONENT,
            pickProps(props){return props;}
        };
    },
    getInitialState(){
        return {};
    },
    /** @inheritdoc */
    propTypes: {
        //Store object.
        pickProps: type('func'),
        service: type('func'),
        store: type('object').isRequired
    },
    /**
     *  Build the action from.
     */
    _buildAction(){
        this._action = this.props.action || actionBuilder({
            service: this.props.service,
            identifier: this.props.store.identifier,
            getListOptions: () => {return this.props.store.getValue.call(this.props.store); } // Binding the store in the function call
        });
    },
    /**
     * Read the state from the store.
     * @return {object} - The object read from the store.
     */
    _getStateFromStore(){
        let store = this.props.store;
        return store.getValue();
    },
    /**
     * Hanlde the list store change.
     */
    _handleStoreChanged(){
        this.setState(this._getStateFromStore());
    },
    /**
     * Register the store nodes.
     */
    _registerStoreNode(){
        STORE_NODE.forEach((node)=>{
            //Maybe this is a bit too much, a global change event could be more efficient as almost all store props change.
            this.props.store[_listenerProp(node)](this._handleStoreChanged)
        });
        //When the criteria is changed, the search is triggered.
        this.props.store.addCriteriaChangeListener(()=>{
            this._action.load();
        })
    },
    /**
     * build the list props.
     * @return {object} - the list property.
     */
    _buildListProps(){
        let {props, state} = this;
        let {dataList, totalCount} = state;
        dataList = dataList || [];
        return assign(props, state, {
            data: dataList,
            fetchNextPage: this._action.load,
            hasMoreData: dataList.length < totalCount
        });
    },
    /** @inheritdoc */
    componentWillMount(){
        this._registerStoreNode();
        this._buildAction();
        this._action.load();
    },
    /** @inheritdoc */
    render(){
        let listProps = this._buildListProps();
        return <this.props.ListComponent {...listProps} />;
    }
};

module.exports = builder(listPageMixin);
<|endoftext|>


<commit_before>// auth.js
var Util = require('../../utils/util.js');
var app = getApp();
Page({
  data: {

  },

  submitForm: function(e){
    console.log("提交授权表单formId:",e.detail.formId);
    var formId = e.detail.formId;
    var name = e.detail.value.name;
    var comment = e.detail.value.comment;
    var nameLen = name.replace(/(^\s*)|(\s*$)/g, "").length;
    if (name.length > 4 || nameLen == 0){
      wx.showToast({
        title: '名字长度要求为1-4个字！'
      })
    return;
    }
    var commentLen = comment.replace(/(^\s*)|(\s*$)/g, "").length;
    if(comment.length > 50){
      wx.showToast({
        title: '备注长度不能超过50个字！'
      })
      return;
    }
    //发起授权申请
    sendAuthRequest(name,comment,formId);
  }
})

function sendAuthRequest(name, comment,formId){
  console.log("name:" + name + ",comment:" + comment +",formId:"+formId);
  wx.getStorage({
    key: 'session',
    success: function (res) {
      var session = res.data;
      wx.request({
        url: app.REQUEST_URL + '/api/information/applyAuth',
        method: 'POST',
        data: {name: name,comment:comment,formId:formId},
        header: {
          session: app.SESSION,
          "content-type": "application/x-www-form-urlencoded;charset=UTF-8"
        },
        success: function (res) {
            console.log("已发送授权申请")
            wx.showModal({
              title: '提示',
              content: '授权申请发送成功，请耐心等待授权结果',
              showCancel:false,
              success:function(){
                wx.redirectTo({
                  url: '/pages/launch/launch',
                })
              }
            })
        }
      })
    },
    fail: function () {
      console.log("session is null，需要重新登录");
    }
  })

}<commit_msg>删除授权申请的session验证<commit_after>// auth.js
var Util = require('../../utils/util.js');
var app = getApp();
Page({
  data: {

  },

  submitForm: function(e){
    console.log("提交授权表单formId:",e.detail.formId);
    var formId = e.detail.formId;
    var name = e.detail.value.name;
    var comment = e.detail.value.comment;
    var nameLen = name.replace(/(^\s*)|(\s*$)/g, "").length;
    if (name.length > 4 || nameLen == 0){
      wx.showToast({
        title: '名字长度要求为1-4个字！'
      })
    return;
    }
    var commentLen = comment.replace(/(^\s*)|(\s*$)/g, "").length;
    if(comment.length > 50){
      wx.showToast({
        title: '备注长度不能超过50个字！'
      })
      return;
    }
    //发起授权申请
    sendAuthRequest(name,comment,formId);
  }
})

function sendAuthRequest(name, comment,formId){
  console.log("name:" + name + ",comment:" + comment +",formId:"+formId);
  wx.getStorage({
    key: 'session',
    success: function (res) {
      var session = res.data;
      wx.request({
        url: app.REQUEST_URL + '/api/information/applyAuth',
        method: 'POST',
        data: {name: name,comment:comment,formId:formId},
        header: {
          "content-type": "application/x-www-form-urlencoded;charset=UTF-8"
        },
        success: function (res) {
            console.log("已发送授权申请")
            wx.showModal({
              title: '提示',
              content: '授权申请发送成功，请耐心等待授权结果',
              showCancel:false,
              success:function(){
                wx.redirectTo({
                  url: '/pages/launch/launch',
                })
              }
            })
        }
      })
    },
    fail: function () {
      console.log("session is null，需要重新登录");
    }
  })

}<|endoftext|>


<commit_before>/*
 *
 * WordPres版微信小程序
 * author: jianbo
 * organization: 守望轩  www.watch-life.net
 * github:    https://github.com/iamxjb/winxin-app-watch-life.net
 * 技术支持微信号：iamxjb
 * 开源协议：MIT
 *
 *  *Copyright (c) 2017 https://www.watch-life.net All rights reserved.
 */

var Api = require('../../utils/api.js');
var util = require('../../utils/util.js');
var WxParse = require('../../wxParse/wxParse.js');
var wxApi = require('../../utils/wxApi.js')
var wxRequest = require('../../utils/wxRequest.js')

import config from '../../utils/config.js'
var pageCount = config.getPageCount;

Page({
  data: {
    title: '文章列表',
    postsList: {},
    pagesList: {},
    categoriesList: {},
    postsShowSwiperList: {},
    isLastPage: false,
    page: 1,
    search: '',
    categories: 0,
    categoriesName:'',
    categoriesImage:"",
    showerror:"none",
    isCategoryPage:"none",
    isSearchPage:"none",
    showallDisplay: "block",
    displaySwiper: "block",
    floatDisplay: "none",
    searchKey:"",
  },
  formSubmit: function (e) {
    var url = '../list/list'
    if (e.detail.value.input != '') {
      url = url + '?search=' + e.detail.value.input;
    }
    wx.navigateTo({
      url: url
    })
  },
  onShareAppMessage: function () {

    var title = "分享“守望轩”";
    var path =""

    if (this.data.categories && this.data.categories != 0)
  {
      title += "的专题：" + this.data.categoriesList.name;
      path = 'pages/list/list?categoryID=' + this.data.categoriesList.id;

  }
  else
  {
      title += "的搜索内容：" + this.data.searchKey;
      path = 'pages/list/list?search=' + this.data.searchKey;
  }

    return {
      title: title,
      path: path,
      success: function (res) {
        // 转发成功
      },
      fail: function (res) {
        // 转发失败
      }
    }
  },
  reload:function(e)
  {
    var self = this;
    if (self.data.categories && self.data.categories != 0) {

      self.setData({
       // categories: options.categoryID,
        isCategoryPage: "block",
        showallDisplay: "none",
        showerror: "none",

      });
      self.fetchCategoriesData(self.data.categories);
    }
    if (self.data.search && self.data.search != '') {
      self.setData({
        //search: options.search,
        isSearchPage: "block",
        showallDisplay: "none",
        showerror: "none",
        searchKey: self.data.search
      })
    }
    self.fetchPostsData(self.data);
  },
  //加载分页
  loadMore: function (e) {
    var self = this;
    if (!self.data.isLastPage) {
      self.setData({
        page: self.data.page + 1
      });
      console.log('当前页' + self.data.page);
      this.fetchPostsData(self.data);
    }
    else {
      wx.showToast({
        title: '没有更多内容',
        mask: false,
        duration: 1000
      });
    }
  },
  onLoad: function (options) {
    var self = this;
    if (options.categoryID && options.categoryID != 0) {
      self.setData({
        categories: options.categoryID,
        isCategoryPage:"block"

      });
      self.fetchCategoriesData(options.categoryID);
    }
    if (options.search && options.search != '') {
      wx.setNavigationBarTitle({
        title: "搜索关键字："+options.search,
        success: function (res) {
          // success
        }
      });
      self.setData({
        search: options.search,
        isSearchPage:"block",
        searchKey: options.search
      })

      this.fetchPostsData(self.data);
    }
  },
  //获取文章列表数据
  fetchPostsData: function (data) {
    var self = this;
    if (!data) data = {};
    if (!data.page) data.page = 1;
    if (!data.categories) data.categories = 0;
    if (!data.search) data.search = '';
    if (data.page === 1) {
      self.setData({
        postsList: []
      });
    };

    wx.showLoading({
      title: '正在加载',
      mask:true
    });

    var getPostsRequest = wxRequest.getRequest(Api.getPosts(data));

    getPostsRequest.then(response =>{

        if (response.statusCode === 200) {
            if (response.data.length < pageCount) {
                self.setData({
                    isLastPage: true
                });
            };
            self.setData({
                floatDisplay: "block",
                showallDisplay: "block",
                postsList: self.data.postsList.concat(response.data.map(function (item) {
                    var strdate = item.date
                    if (item.category_name != null) {

                        item.categoryImage = "../../images/topic.png";
                    }
                    else {
                        item.categoryImage = "";
                    }

                    if (item.post_thumbnail_image == null || item.post_thumbnail_image == '') {
                        item.post_thumbnail_image = '../../images/logo700.png';
                    }
                    item.date = util.cutstr(strdate, 10, 1);
                    return item;
                })),

            });
            // setTimeout(function () {
            //     wx.hideLoading();

            // }, 1500);

        }
        else {
            if (response.data.code == "rest_post_invalid_page_number") {

                self.setData({
                    isLastPage: true
                });

            }
            else {
                wx.showToast({
                    title: response.data.message,
                    duration: 1500
                })
            }
        }

    })
    .catch(function(){
        if (data.page == 1) {

            self.setData({
                showerror: "block",
                floatDisplay: "none"
            });

        }
        else {
            wx.showModal({
                title: '加载失败',
                content: '加载数据失败,请重试.',
                showCancel: false,
            });

            self.setData({
                page: data.page - 1
            });
        }

    })
        .finally(function () {
            wx.hideLoading();

        })
  },

  // 跳转至查看文章详情
  redictDetail: function (e) {
    // console.log('查看文章');
    var id = e.currentTarget.id,
      url = '../detail/detail?id=' + id;
    wx.navigateTo({
      url: url
    })
  },

  //获取分类列表
  fetchCategoriesData: function (id) {
    var self = this;
    self.setData({
      categoriesList: []
    });

    var getCategoryRequest = wxRequest.getRequest(Api.getCategoryByID(id));

    getCategoryRequest.then(response =>{

        var catImage = "";
        if (typeof (response.data.category_thumbnail_image) == "undefined" || response.data.category_thumbnail_image == "") {
            catImage = "../../images/website.png";
        }
        else {
            catImage = response.data.category_thumbnail_image;
        }

        self.setData({
            categoriesList: response.data,
            categoriesImage: catImage,
            categoriesName: response.name
        });

        wx.setNavigationBarTitle({
            title: response.data.name,
            success: function (res) {
                // success
            }
        });

        self.fetchPostsData(self.data);

    })
  },

})

<commit_msg>修正目录分类页面的代码错误<commit_after>/*
 *
 * WordPres版微信小程序
 * author: jianbo
 * organization: 守望轩  www.watch-life.net
 * github:    https://github.com/iamxjb/winxin-app-watch-life.net
 * 技术支持微信号：iamxjb
 * 开源协议：MIT
 *
 *  *Copyright (c) 2017 https://www.watch-life.net All rights reserved.
 */

var Api = require('../../utils/api.js');
var util = require('../../utils/util.js');
var WxParse = require('../../wxParse/wxParse.js');
var wxApi = require('../../utils/wxApi.js')
var wxRequest = require('../../utils/wxRequest.js')

import config from '../../utils/config.js'
var pageCount = config.getPageCount;

Page({
  data: {
    title: '文章列表',
    postsList: {},
    pagesList: {},
    categoriesList: {},
    postsShowSwiperList: {},
    isLastPage: false,
    page: 1,
    search: '',
    categories: 0,
    categoriesName:'',
    categoriesImage:"",
    showerror:"none",
    isCategoryPage:"none",
    isSearchPage:"none",
    showallDisplay: "block",
    displaySwiper: "block",
    floatDisplay: "none",
    searchKey:"",
  },
  formSubmit: function (e) {
    var url = '../list/list'
    if (e.detail.value.input != '') {
      url = url + '?search=' + e.detail.value.input;
    }
    wx.navigateTo({
      url: url
    })
  },
  onShareAppMessage: function () {

    var title = "分享“守望轩”";
    var path =""

    if (this.data.categories && this.data.categories != 0)
  {
      title += "的专题：" + this.data.categoriesList.name;
      path = 'pages/list/list?categoryID=' + this.data.categoriesList.id;

  }
  else
  {
      title += "的搜索内容：" + this.data.searchKey;
      path = 'pages/list/list?search=' + this.data.searchKey;
  }

    return {
      title: title,
      path: path,
      success: function (res) {
        // 转发成功
      },
      fail: function (res) {
        // 转发失败
      }
    }
  },
  reload:function(e)
  {
    var self = this;
    if (self.data.categories && self.data.categories != 0) {

      self.setData({
       // categories: options.categoryID,
        isCategoryPage: "block",
        showallDisplay: "none",
        showerror: "none",

      });
      self.fetchCategoriesData(self.data.categories);
    }
    if (self.data.search && self.data.search != '') {
      self.setData({
        //search: options.search,
        isSearchPage: "block",
        showallDisplay: "none",
        showerror: "none",
        searchKey: self.data.search
      })
    }
    self.fetchPostsData(self.data);
  },
  //加载分页
  loadMore: function (e) {
    var self = this;
    if (!self.data.isLastPage) {
      self.setData({
        page: self.data.page + 1
      });
      console.log('当前页' + self.data.page);
      this.fetchPostsData(self.data);
    }
    else {
      wx.showToast({
        title: '没有更多内容',
        mask: false,
        duration: 1000
      });
    }
  },
  onLoad: function (options) {
    var self = this;
    if (options.categoryID && options.categoryID != 0) {
      self.setData({
        categories: options.categoryID,
        isCategoryPage:"block"

      });
      self.fetchCategoriesData(options.categoryID);
    }
    if (options.search && options.search != '') {
      wx.setNavigationBarTitle({
        title: "搜索关键字："+options.search,
        success: function (res) {
          // success
        }
      });
      self.setData({
        search: options.search,
        isSearchPage:"block",
        searchKey: options.search
      })

      this.fetchPostsData(self.data);
    }
  },
  //获取文章列表数据
  fetchPostsData: function (data) {
    var self = this;
    if (!data) data = {};
    if (!data.page) data.page = 1;
    if (!data.categories) data.categories = 0;
    if (!data.search) data.search = '';
    if (data.page === 1) {
      self.setData({
        postsList: []
      });
    };

    wx.showLoading({
      title: '正在加载',
      mask:true
    });

    var getPostsRequest = wxRequest.getRequest(Api.getPosts(data));

    getPostsRequest.then(response =>{

        if (response.statusCode === 200) {
            if (response.data.length < pageCount) {
                self.setData({
                    isLastPage: true
                });
            };
            self.setData({
                floatDisplay: "block",
                showallDisplay: "block",
                postsList: self.data.postsList.concat(response.data.map(function (item) {
                    var strdate = item.date
                    if (item.category_name != null) {

                        item.categoryImage = "../../images/topic.png";
                    }
                    else {
                        item.categoryImage = "";
                    }

                    if (item.post_thumbnail_image == null || item.post_thumbnail_image == '') {
                        item.post_thumbnail_image = '../../images/logo700.png';
                    }
                    item.date = util.cutstr(strdate, 10, 1);
                    return item;
                })),

            });
            // setTimeout(function () {
            //     wx.hideLoading();

            // }, 1500);

        }
        else {
            if (response.data.code == "rest_post_invalid_page_number") {

                self.setData({
                    isLastPage: true
                });

            }
            else {
                wx.showToast({
                    title: response.data.message,
                    duration: 1500
                })
            }
        }

    })
    .catch(function(){
        if (data.page == 1) {

            self.setData({
                showerror: "block",
                floatDisplay: "none"
            });

        }
        else {
            wx.showModal({
                title: '加载失败',
                content: '加载数据失败,请重试.',
                showCancel: false,
            });

            self.setData({
                page: data.page - 1
            });
        }

    })
        .finally(function () {
            wx.hideLoading();

        })
  },

  // 跳转至查看文章详情
  redictDetail: function (e) {
    // console.log('查看文章');
    var id = e.currentTarget.id,
      url = '../detail/detail?id=' + id;
    wx.navigateTo({
      url: url
    })
  },

  //获取分类列表
  fetchCategoriesData: function (id) {
    var self = this;
    self.setData({
      categoriesList: []
    });

    var getCategoryRequest = wxRequest.getRequest(Api.getCategoryByID(id));

    getCategoryRequest.then(response =>{

        var catImage = "";
        if (typeof (response.data.category_thumbnail_image) == "undefined" || response.data.category_thumbnail_image == "") {
            catImage = "../../images/website.png";
        }
        else {
            catImage = response.data.category_thumbnail_image;
        }

        self.setData({
            categoriesList: response.data,
            categoriesImage: catImage,
            categoriesName: response.data.name
        });

        wx.setNavigationBarTitle({
            title: response.data.name,
            success: function (res) {
                // success
            }
        });

        self.fetchPostsData(self.data);

    })
  },

})

<|endoftext|>