<commit_before>import DS from 'ember-data';

export default DS.RESTAdapter.extend({
  defaultSerializer: 'endpoints',
  buildURL: function(type, id, record) {
    var url = this._super(type, id, record);
    var includes = [];
    var model = this.container.lookupFactory('model:' + type);
    model.eachRelationship(function(name, descriptor) {
      if (!descriptor.options.async) {
        includes.push(name);
      }
    });

    if (includes.length) {
      return url + '?include=' + includes.join(',');
    }

    return url;
  }
});
<commit_msg>Use dasherized urls for path names<commit_after>import DS from 'ember-data';

export default DS.RESTAdapter.extend({
  defaultSerializer: 'endpoints',
  buildURL: function(type, id, record) {
    var url = this._super(type, id, record);
    var includes = [];
    var model = this.container.lookupFactory('model:' + type);
    model.eachRelationship(function(name, descriptor) {
      if (!descriptor.options.async) {
        includes.push(name);
      }
    });

    if (includes.length) {
      return url + '?include=' + includes.join(',');
    }

    return url;
  },
  // Workaround where REST URLs were getting camelCased
  // https://github.com/ember-cli/ember-cli/issues/2906
  pathForType: function(type) {
    var dasherized = Ember.String.dasherize(type);
    return Ember.String.pluralize(dasherized);
  }
});
<|endoftext|>


<commit_before>import { Spinner } from '../../consumables/js/es2015/index.js';

describe('Test spinner', function () {
  describe('Constructor', function () {
    it(`Should throw if root element is not given`, function () {
      expect(() => {
        new Spinner();
      }).to.throw;
    });

    it(`Should throw if root element is not a DOM element`, function () {
      expect(() => {
        new Spinner(document.createTextNode(''));
      }).to.throw;
    });

    it(`Should default state to active`, function () {
      const spinner = new Spinner(document.createElement('div'));
      expect(spinner.isActive()).to.equal(true);
    });

    it(`Should accept options`, function () {
      const options = { active: false };
      const spinner = new Spinner(document.createElement('div'), options);
      expect(spinner.isActive()).to.equal(false);
    });
  });

  describe('set()', function () {
    it('Should throw if boolean is not passed in', function () {
      const spinner = new Spinner(document.createElement('div'));
      expect(() => spinner.set()).to.throw;
      expect(() => spinner.set('true')).to.throw;
    });

    it('Should set state', function () {
      const spinner = new Spinner(document.createElement('div'));
      spinner.set(true);
      expect(spinner.isActive()).to.equal(true);
      spinner.set(false);
      expect(spinner.isActive()).to.equal(false);
    });

    it('Should return self after setting', function () {
      const spinner = new Spinner(document.createElement('div'));
      expect(spinner.set(true)).to.equal(spinner);
    });

    it('Should set class of DOM element', function () {
      const spinner = new Spinner(document.createElement('div'));
      spinner.set(true);
      expect(spinner.element.className).to.equal('');
      spinner.set(false);
      expect(spinner.element.className).to.equal('is-stopping');
    });

    it('Should set special class for IE', function () {
      const options = { ie: true };
      const spinner = new Spinner(document.createElement('div'), options);
      spinner.set(true);
      expect(spinner.element.className).to.equal('is--ie');
      spinner.set(false);
      expect(spinner.element.className).to.equal('is--ie is-stopping--ie');
    });
  });

  describe('toggle()', function () {
    it('Should toggle', function () {
      const spinner = new Spinner(document.createElement('div'));
      spinner.toggle();
      expect(spinner.isActive()).to.equal(false);
      spinner.toggle();
      expect(spinner.isActive()).to.equal(true);
    });
  });

  describe('isActive()', function () {
    it('Should return spinner state', function () {
      const spinner = new Spinner(document.createElement('div'));
      expect(spinner.isActive()).to.equal(true);
    });
  });

  describe('Managing instances', function () {
    let element;

    before(function () {
      element = document.createElement('a');
    });

    it('Should prevent creating duplicate instances', function () {
      let first;
      let second;
      try {
        first = Spinner.create(element);
        second = Spinner.create(element);
        expect(first).to.equal(second);
      } finally {
        first && first.release();
        if (first !== second) {
          second && second.release();
        }
      }
    });

    it('Should let create a new instance for an element if an earlier one has been released', function () {
      let first;
      let second;
      try {
        first = Spinner.create(element);
        first.release();
        second = Spinner.create(element);
        expect(first).not.to.equal(second);
      } finally {
        first && first.release();
        if (first !== second) {
          second && second.release();
        }
      }
    });
  });
});
<commit_msg>Check if IE is running for the test toggling spinner state, fixes #966.<commit_after>import { Spinner } from '../../consumables/js/es2015/index.js';

describe('Test spinner', function () {
  describe('Constructor', function () {
    it(`Should throw if root element is not given`, function () {
      expect(() => {
        new Spinner();
      }).to.throw;
    });

    it(`Should throw if root element is not a DOM element`, function () {
      expect(() => {
        new Spinner(document.createTextNode(''));
      }).to.throw;
    });

    it(`Should default state to active`, function () {
      const spinner = new Spinner(document.createElement('div'));
      expect(spinner.isActive()).to.equal(true);
    });

    it(`Should accept options`, function () {
      const options = { active: false };
      const spinner = new Spinner(document.createElement('div'), options);
      expect(spinner.isActive()).to.equal(false);
    });
  });

  describe('set()', function () {
    it('Should throw if boolean is not passed in', function () {
      const spinner = new Spinner(document.createElement('div'));
      expect(() => spinner.set()).to.throw;
      expect(() => spinner.set('true')).to.throw;
    });

    it('Should set state', function () {
      const spinner = new Spinner(document.createElement('div'));
      spinner.set(true);
      expect(spinner.isActive()).to.equal(true);
      spinner.set(false);
      expect(spinner.isActive()).to.equal(false);
    });

    it('Should return self after setting', function () {
      const spinner = new Spinner(document.createElement('div'));
      expect(spinner.set(true)).to.equal(spinner);
    });

    it('Should set class of DOM element', function () {
      const isIE = window.ActiveXObject || 'ActiveXObject' in window;
      const spinner = new Spinner(document.createElement('div'));
      spinner.set(true);
      expect(spinner.element.className).to.equal(isIE ? 'is--ie' : '');
      spinner.set(false);
      expect(spinner.element.className).to.equal(isIE ? 'is--ie is-stopping--ie' : 'is-stopping');
    });

    it('Should set special class for IE', function () {
      const options = { ie: true };
      const spinner = new Spinner(document.createElement('div'), options);
      spinner.set(true);
      expect(spinner.element.className).to.equal('is--ie');
      spinner.set(false);
      expect(spinner.element.className).to.equal('is--ie is-stopping--ie');
    });
  });

  describe('toggle()', function () {
    it('Should toggle', function () {
      const spinner = new Spinner(document.createElement('div'));
      spinner.toggle();
      expect(spinner.isActive()).to.equal(false);
      spinner.toggle();
      expect(spinner.isActive()).to.equal(true);
    });
  });

  describe('isActive()', function () {
    it('Should return spinner state', function () {
      const spinner = new Spinner(document.createElement('div'));
      expect(spinner.isActive()).to.equal(true);
    });
  });

  describe('Managing instances', function () {
    let element;

    before(function () {
      element = document.createElement('a');
    });

    it('Should prevent creating duplicate instances', function () {
      let first;
      let second;
      try {
        first = Spinner.create(element);
        second = Spinner.create(element);
        expect(first).to.equal(second);
      } finally {
        first && first.release();
        if (first !== second) {
          second && second.release();
        }
      }
    });

    it('Should let create a new instance for an element if an earlier one has been released', function () {
      let first;
      let second;
      try {
        first = Spinner.create(element);
        first.release();
        second = Spinner.create(element);
        expect(first).not.to.equal(second);
      } finally {
        first && first.release();
        if (first !== second) {
          second && second.release();
        }
      }
    });
  });
});
<|endoftext|>


<commit_before>import { useQuery } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React from 'react'
// import * as Yup from 'yup'

// import { Link, IconButton } from 'src/components/buttons'
// import { TextInput } from 'src/components/inputs'
import { NumberInput } from 'src/components/inputs/formik'
import DataTable from 'src/components/tables/DataTable'
// import { ReactComponent as EditIconDisabled } from 'src/styling/icons/action/edit/disabled.svg'
// import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
import { formatDate } from 'src/utils/timezones'

const GET_BATCHES = gql`
  query cashboxBatches {
    cashboxBatches {
      id
      deviceId
      created
      operationType
      customBillCount
      performedBy
      bills {
        fiat
        deviceId
        created
        cashbox
      }
    }
  }
`

/* const EDIT_BATCH = gql`
  mutation editBatch($id: ID, $performedBy: String) {
    editBatch(id: $id, performedBy: $performedBy) {
      id
    }
  }
` */

const GET_DATA = gql`
  query getData {
    config
  }
`

const styles = {
  operationType: {
    marginLeft: 8
  },
  operationTypeWrapper: {
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center'
  },
  saveAndCancel: {
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'space-between'
  }
}

/* const schema = Yup.object().shape({
  performedBy: Yup.string().nullable()
}) */

const useStyles = makeStyles(styles)

const CashboxHistory = ({ machines, currency }) => {
  const classes = useStyles()

  /* const [error, setError] = useState(false)
  const [field, setField] = useState(null)
  const [editing, setEditing] = useState(false) */

  const { data: batchesData, loading: batchesLoading } = useQuery(GET_BATCHES)

  /* const [editBatch] = useMutation(EDIT_BATCH, {
    refetchQueries: () => ['cashboxBatches']
  }) */

  const { data: configData, loading: configLoading } = useQuery(GET_DATA)
  const timezone = R.path(['config', 'locale_timezone'], configData)

  const loading = batchesLoading || configLoading

  const batches = R.path(['cashboxBatches'])(batchesData)

  const getOperationRender = R.reduce(
    (ret, i) =>
      R.pipe(
        R.assoc(
          `cash-cassette-${i}-refill`,
          <>
            <TxOutIcon />

              Cash cassette {i} refill

          </>
        ),
        R.assoc(
          `cash-cassette-${i}-empty`,
          <>
            <TxOutIcon />

              Cash cassette {i} emptied

          </>
        )
      )(ret),
    {
      'cash-box-empty': (
        <>
          <TxInIcon />
          Cash box emptied
        </>
      )
    },
    R.range(1, 5)
  )

  /* const save = row => {
    const performedBy = field.performedBy === '' ? null : field.performedBy

    schema
      .isValid(field)
      .then(() => {
        setError(false)
        editBatch({
          variables: { id: row.id, performedBy: performedBy }
        })
      })
      .catch(setError(true))
    return close()
  }

  const close = () => {
    setEditing(false)
    setField(null)
  }

  const notEditing = id => field?.id !== id */

  const elements = [
    {
      name: 'operation',
      header: 'Operation',
      width: 200,
      textAlign: 'left',
      view: it => (

          {getOperationRender[it.operationType]}

      )
    },
    {
      name: 'machine',
      header: 'Machine',
      width: 200,
      textAlign: 'left',
      view: it => {
        return R.find(R.propEq('id', it.deviceId))(machines).name
      }
    },
    {
      name: 'billCount',
      header: 'Bill Count',
      width: 115,
      textAlign: 'left',
      input: NumberInput,
      inputProps: {
        decimalPlaces: 0
      },
      view: it =>
        R.isNil(it.customBillCount) ? it.bills.length : it.customBillCount
    },
    {
      name: 'total',
      header: 'Total',
      width: 180,
      textAlign: 'right',
      view: it => (

          {R.sum(R.map(b => R.prop('fiat', b), it.bills))} {currency}

      )
    },
    {
      name: 'date',
      header: 'Date',
      width: 135,
      textAlign: 'right',
      view: it => formatDate(it.created, timezone, 'yyyy-MM-dd')
    },
    {
      name: 'time',
      header: 'Time (h:m)',
      width: 125,
      textAlign: 'right',
      view: it => formatDate(it.created, timezone, 'HH:mm')
    }
    /* {
      name: 'performedBy',
      header: 'Performed by',
      width: 180,
      textAlign: 'left',
      view: it => {
        if (notEditing(it.id))
          return R.isNil(it.performedBy) ? 'Unknown entity' : it.performedBy
        return (
          <TextInput
            onChange={e => setField({ ...field, performedBy: e.target.value })}
            error={error}
            width={190 * 0.85}
            value={field?.performedBy}
          />
        )
      }
    },
    {
      name: '',
      header: 'Edit',
      width: 80,
      textAlign: 'right',
      view: it => {
        if (notEditing(it.id))
          return (
            <IconButton
              disabled={editing}
              onClick={() => {
                setField({ id: it.id, performedBy: it.performedBy })
                setEditing(true)
              }}>
              {editing ? <EditIconDisabled /> : <EditIcon />}
            </IconButton>
          )
        return (

            <Link type="submit" color="primary" onClick={() => save(it)}>
              Save
            </Link>
            <Link color="secondary" onClick={close}>
              Cancel
            </Link>

        )
      }
    } */
  ]

  return (
    <DataTable
      loading={loading}
      name="cashboxHistory"
      elements={elements}
      data={batches}
      emptyText="No cashbox batches so far"
    />
  )
}

export default CashboxHistory
<commit_msg>fix: remove undefined field querying<commit_after>import { useQuery } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React from 'react'
// import * as Yup from 'yup'

// import { Link, IconButton } from 'src/components/buttons'
// import { TextInput } from 'src/components/inputs'
import { NumberInput } from 'src/components/inputs/formik'
import DataTable from 'src/components/tables/DataTable'
// import { ReactComponent as EditIconDisabled } from 'src/styling/icons/action/edit/disabled.svg'
// import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
import { formatDate } from 'src/utils/timezones'

const GET_BATCHES = gql`
  query cashboxBatches {
    cashboxBatches {
      id
      deviceId
      created
      operationType
      customBillCount
      performedBy
      bills {
        fiat
        deviceId
        created
      }
    }
  }
`

/* const EDIT_BATCH = gql`
  mutation editBatch($id: ID, $performedBy: String) {
    editBatch(id: $id, performedBy: $performedBy) {
      id
    }
  }
` */

const GET_DATA = gql`
  query getData {
    config
  }
`

const styles = {
  operationType: {
    marginLeft: 8
  },
  operationTypeWrapper: {
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center'
  },
  saveAndCancel: {
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'space-between'
  }
}

/* const schema = Yup.object().shape({
  performedBy: Yup.string().nullable()
}) */

const useStyles = makeStyles(styles)

const CashboxHistory = ({ machines, currency }) => {
  const classes = useStyles()

  /* const [error, setError] = useState(false)
  const [field, setField] = useState(null)
  const [editing, setEditing] = useState(false) */

  const { data: batchesData, loading: batchesLoading } = useQuery(GET_BATCHES)

  /* const [editBatch] = useMutation(EDIT_BATCH, {
    refetchQueries: () => ['cashboxBatches']
  }) */

  const { data: configData, loading: configLoading } = useQuery(GET_DATA)
  const timezone = R.path(['config', 'locale_timezone'], configData)

  const loading = batchesLoading || configLoading

  const batches = R.path(['cashboxBatches'])(batchesData)

  const getOperationRender = R.reduce(
    (ret, i) =>
      R.pipe(
        R.assoc(
          `cash-cassette-${i}-refill`,
          <>
            <TxOutIcon />

              Cash cassette {i} refill

          </>
        ),
        R.assoc(
          `cash-cassette-${i}-empty`,
          <>
            <TxOutIcon />

              Cash cassette {i} emptied

          </>
        )
      )(ret),
    {
      'cash-box-empty': (
        <>
          <TxInIcon />
          Cash box emptied
        </>
      )
    },
    R.range(1, 5)
  )

  /* const save = row => {
    const performedBy = field.performedBy === '' ? null : field.performedBy

    schema
      .isValid(field)
      .then(() => {
        setError(false)
        editBatch({
          variables: { id: row.id, performedBy: performedBy }
        })
      })
      .catch(setError(true))
    return close()
  }

  const close = () => {
    setEditing(false)
    setField(null)
  }

  const notEditing = id => field?.id !== id */

  const elements = [
    {
      name: 'operation',
      header: 'Operation',
      width: 200,
      textAlign: 'left',
      view: it => (

          {getOperationRender[it.operationType]}

      )
    },
    {
      name: 'machine',
      header: 'Machine',
      width: 200,
      textAlign: 'left',
      view: it => {
        return R.find(R.propEq('id', it.deviceId))(machines).name
      }
    },
    {
      name: 'billCount',
      header: 'Bill Count',
      width: 115,
      textAlign: 'left',
      input: NumberInput,
      inputProps: {
        decimalPlaces: 0
      },
      view: it =>
        R.isNil(it.customBillCount) ? it.bills.length : it.customBillCount
    },
    {
      name: 'total',
      header: 'Total',
      width: 180,
      textAlign: 'right',
      view: it => (

          {R.sum(R.map(b => R.prop('fiat', b), it.bills))} {currency}

      )
    },
    {
      name: 'date',
      header: 'Date',
      width: 135,
      textAlign: 'right',
      view: it => formatDate(it.created, timezone, 'yyyy-MM-dd')
    },
    {
      name: 'time',
      header: 'Time (h:m)',
      width: 125,
      textAlign: 'right',
      view: it => formatDate(it.created, timezone, 'HH:mm')
    }
    /* {
      name: 'performedBy',
      header: 'Performed by',
      width: 180,
      textAlign: 'left',
      view: it => {
        if (notEditing(it.id))
          return R.isNil(it.performedBy) ? 'Unknown entity' : it.performedBy
        return (
          <TextInput
            onChange={e => setField({ ...field, performedBy: e.target.value })}
            error={error}
            width={190 * 0.85}
            value={field?.performedBy}
          />
        )
      }
    },
    {
      name: '',
      header: 'Edit',
      width: 80,
      textAlign: 'right',
      view: it => {
        if (notEditing(it.id))
          return (
            <IconButton
              disabled={editing}
              onClick={() => {
                setField({ id: it.id, performedBy: it.performedBy })
                setEditing(true)
              }}>
              {editing ? <EditIconDisabled /> : <EditIcon />}
            </IconButton>
          )
        return (

            <Link type="submit" color="primary" onClick={() => save(it)}>
              Save
            </Link>
            <Link color="secondary" onClick={close}>
              Cancel
            </Link>

        )
      }
    } */
  ]

  return (
    <DataTable
      loading={loading}
      name="cashboxHistory"
      elements={elements}
      data={batches}
      emptyText="No cashbox batches so far"
    />
  )
}

export default CashboxHistory
<|endoftext|>


<commit_before>var ipc = window.require('ipc');
var Reflux = require('reflux');
var _ = require('underscore');

var Actions = require('../actions/actions');
var SettingsStore = require('../stores/settings');

var SoundNotificationStore = Reflux.createStore({
  listenables: Actions,

  init: function () {
    this._previousNotifications = [];
    this._audio = new Audio('sounds/digi.wav');
  },

  playSound: function () {
    this._audio.play();
  },

  showNotification: function (countNew, response, latestNotification) {
    var title = (countNew == 1 ?
      'Gitify - ' + latestNotification.full_name :
      'Gitify');
    var body = (countNew == 1 ?
      latestNotification.subject :
      'You\'ve got ' + countNew + ' notifications.');
    var nativeNotification = new Notification(title, {
      body: body
    });
    nativeNotification.onclick = function () {
      ipc.sendChannel('reopen-window');
    };
  },

  onIsNewNotification: function (response) {
    var self = this;
    var playSound = SettingsStore.getSettings().playSound;
    var showNotifications = SettingsStore.getSettings().showNotifications;

    if (!playSound && !showNotifications) { return; }

    // Check if notification is already in the store.
    var newNotifications = _.filter(response, function (obj) {
      return !_.contains(self._previousNotifications, obj.id);
    });

    // Play Sound / Show Notification.
    if (newNotifications && newNotifications.length) {
      if (playSound) {
        self.playSound();
      }
      if (showNotifications) {
        this.showNotification(newNotifications.length, response, {
          full_name: newNotifications[0].repository.full_name,
          subject: newNotifications[0].subject.title
        });
      }
    }

    // Now Reset the previousNotifications array.
    self._previousNotifications = _.map(response, function (obj) {
      return obj.id;
    });
  }

});

module.exports = SoundNotificationStore;
<commit_msg>Revert setting audio in store's init<commit_after>var ipc = window.require('ipc');
var Reflux = require('reflux');
var _ = require('underscore');

var Actions = require('../actions/actions');
var SettingsStore = require('../stores/settings');

var SoundNotificationStore = Reflux.createStore({
  listenables: Actions,

  init: function () {
    this._previousNotifications = [];
  },

  playSound: function () {
    var audio = new Audio('sounds/digi.wav');
    audio.play();
  },

  showNotification: function (countNew, response, latestNotification) {
    var title = (countNew == 1 ?
      'Gitify - ' + latestNotification.full_name :
      'Gitify');
    var body = (countNew == 1 ?
      latestNotification.subject :
      'You\'ve got ' + countNew + ' notifications.');
    var nativeNotification = new Notification(title, {
      body: body
    });
    nativeNotification.onclick = function () {
      ipc.sendChannel('reopen-window');
    };
  },

  onIsNewNotification: function (response) {
    var self = this;
    var playSound = SettingsStore.getSettings().playSound;
    var showNotifications = SettingsStore.getSettings().showNotifications;

    if (!playSound && !showNotifications) { return; }

    // Check if notification is already in the store.
    var newNotifications = _.filter(response, function (obj) {
      return !_.contains(self._previousNotifications, obj.id);
    });

    // Play Sound / Show Notification.
    if (newNotifications && newNotifications.length) {
      if (playSound) {
        self.playSound();
      }
      if (showNotifications) {
        this.showNotification(newNotifications.length, response, {
          full_name: newNotifications[0].repository.full_name,
          subject: newNotifications[0].subject.title
        });
      }
    }

    // Now Reset the previousNotifications array.
    self._previousNotifications = _.map(response, function (obj) {
      return obj.id;
    });
  }

});

module.exports = SoundNotificationStore;
<|endoftext|>


<commit_before>import DS                 from 'ember-data'

import {
  get, getProperties
} from '@ember/object'

import {
  isBlank
} from '@ember/utils'

import {
  objectReject
} from './utils'

import {
  assign
} from '@ember/polyfills'

import {
  inject as service
} from '@ember/service'

import Transport from './transport'

export default DS.RESTAdapter.extend({
  cachedShoe:       service(),
  mergedProperties: ['graphOptions'],

  graphOptions: {
    addTypename: true,
  },

  request(opts) {
    let {query, variables} = opts
    let originalVariables = variables
    let operationName = this.graphHelper('operationName', query)

    query     = this.graphHelper('prepareQuery', query)
    variables = this.graphHelper('normalizeVariables', originalVariables, query)

    let data = {
      variables,
      query:          query.string,
    }
    if(operationName)
      data.operationName = operationName

    let mergedOpts = assign(
      {},
      opts,
      {variables, originalVariables}
    )

    return this.ajax(
      [this.get('host'), this.get('namespace')].join('/'),
      'POST',
      this.requestParams(data, mergedOpts)
    )
    .then(r => this.graphHelper('normalizeResponse', r))
    .then(r => this.handleGraphResponse(r, mergedOpts))
    .catch(e => this.handleGraphError(e, mergedOpts))
  },

  ajaxOptions() {
    let opts = this._super(...arguments)

    if(opts.body && opts.body instanceof FormData) {
      opts.processData = false
      opts.contentType = false
      opts.data = opts.body
    }

    return opts
  },

  requestParams(data, opts) {
    let transportType = null
    try {
      transportType = opts.options.transport
    } catch(e) {
      transportType = 'json'
    }
    return Transport[transportType](...arguments)
  },

  mutate(opts) {
    let query  = opts.mutation
    let variables = opts.variables

    return this.request(
      assign({}, opts, {query, variables})
    )
  },

  query(opts) {
    return this.request(opts)
  },

  handleGraphResponse(response) {
    return response
  },

  handleGraphError(error) {
    return error
  },

  graphHelper(name, ...args) {
    return this.graphHelpers[name].call(this, ...args)
  },

  tokenizeAjaxRequest(url, type, options = {}) {
    let content = {}
    let maybeFormData = (options.body || options.data)
    let separator = this.get('separator')
    let b2a = this.get('cachedShoe.b2a')

    if(typeof FormData !== 'undefined' && maybeFormData instanceof FormData) {
      for (let [k, v] of maybeFormData.entries()) {
        content[k] = v
      }
      content.variables = JSON.parse(content.variables)
    } else {
      content = maybeFormData
    }

    let stringifyObject = (o) => JSON.stringify(o, Object.keys(o).sort())
    let tokenizeString = (s) => b2a.btoa(s.replace(/\\r\\n/g, '\\n').replace(/\s\s+/g, ' '))

    return tokenizeString(
      [url, type, stringifyObject(content)].join(separator)
    )
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/\=+$/, '')
  },

  graphHelpers: {
    operationName(query) {
      try {
        return query.definitions[0].name.value
      } catch(e) {
        return null
      }
    },

    prepareQuery(query) {
      let preparedQuery = assign({}, query)
      if(this.get('graphOptions.addTypename')) preparedQuery.string = preparedQuery.string.replace(/}/g, `  __typename\n}`)
      return preparedQuery
    },

    allowedVariables(query) {
      return query
        .definitions
        .map(
          def => (def.variableDefinitions || []).map(x => get(x, 'variable.name.value'))
        )
        .reduce((vars, acc) => acc.concat(vars), [])
    },

    normalizeVariables(variables, query) {
      if(!variables) return {}
      let allowedVariables = this.graphHelper('allowedVariables', query)

      return objectReject(
        getProperties(variables, allowedVariables),
        isBlank
      )
    },

    normalizeResponse(response) {
      if(response.errors) {
        throw new DS.AdapterError(response.errors)
      } else {
        return this.get('store').serializerFor('application').normalize(response.data)
      }
    }
  }
})
<commit_msg>dynamic service lookup (it may not exists)<commit_after>import DS                 from 'ember-data'

import {
  get, getProperties, computed
} from '@ember/object'

import {
  isBlank
} from '@ember/utils'

import {
  objectReject
} from './utils'

import {
  assign
} from '@ember/polyfills'

import {
  getOwner
} from '@ember/application'

import Transport from './transport'

export default DS.RESTAdapter.extend({
  mergedProperties: ['graphOptions'],

  cachedShoe: computed(function() {
    return getOwner(this).lookup('service:cached-shoe')
  }),

  graphOptions: {
    addTypename: true,
  },

  request(opts) {
    let {query, variables} = opts
    let originalVariables = variables
    let operationName = this.graphHelper('operationName', query)

    query     = this.graphHelper('prepareQuery', query)
    variables = this.graphHelper('normalizeVariables', originalVariables, query)

    let data = {
      variables,
      query:          query.string,
    }
    if(operationName)
      data.operationName = operationName

    let mergedOpts = assign(
      {},
      opts,
      {variables, originalVariables}
    )

    return this.ajax(
      [this.get('host'), this.get('namespace')].join('/'),
      'POST',
      this.requestParams(data, mergedOpts)
    )
    .then(r => this.graphHelper('normalizeResponse', r))
    .then(r => this.handleGraphResponse(r, mergedOpts))
    .catch(e => this.handleGraphError(e, mergedOpts))
  },

  ajaxOptions() {
    let opts = this._super(...arguments)

    if(opts.body && opts.body instanceof FormData) {
      opts.processData = false
      opts.contentType = false
      opts.data = opts.body
    }

    return opts
  },

  requestParams(data, opts) {
    let transportType = null
    try {
      transportType = opts.options.transport
    } catch(e) {
      transportType = 'json'
    }
    return Transport[transportType](...arguments)
  },

  mutate(opts) {
    let query  = opts.mutation
    let variables = opts.variables

    return this.request(
      assign({}, opts, {query, variables})
    )
  },

  query(opts) {
    return this.request(opts)
  },

  handleGraphResponse(response) {
    return response
  },

  handleGraphError(error) {
    return error
  },

  graphHelper(name, ...args) {
    return this.graphHelpers[name].call(this, ...args)
  },

  tokenizeAjaxRequest(url, type, options = {}) {
    let content = {}
    let maybeFormData = (options.body || options.data)
    let separator = this.get('separator')
    let b2a = this.get('cachedShoe.b2a')

    if(typeof FormData !== 'undefined' && maybeFormData instanceof FormData) {
      for (let [k, v] of maybeFormData.entries()) {
        content[k] = v
      }
      content.variables = JSON.parse(content.variables)
    } else {
      content = maybeFormData
    }

    let stringifyObject = (o) => JSON.stringify(o, Object.keys(o).sort())
    let tokenizeString = (s) => b2a.btoa(s.replace(/\\r\\n/g, '\\n').replace(/\s\s+/g, ' '))

    return tokenizeString(
      [url, type, stringifyObject(content)].join(separator)
    )
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/\=+$/, '')
  },

  graphHelpers: {
    operationName(query) {
      try {
        return query.definitions[0].name.value
      } catch(e) {
        return null
      }
    },

    prepareQuery(query) {
      let preparedQuery = assign({}, query)
      if(this.get('graphOptions.addTypename')) preparedQuery.string = preparedQuery.string.replace(/}/g, `  __typename\n}`)
      return preparedQuery
    },

    allowedVariables(query) {
      return query
        .definitions
        .map(
          def => (def.variableDefinitions || []).map(x => get(x, 'variable.name.value'))
        )
        .reduce((vars, acc) => acc.concat(vars), [])
    },

    normalizeVariables(variables, query) {
      if(!variables) return {}
      let allowedVariables = this.graphHelper('allowedVariables', query)

      return objectReject(
        getProperties(variables, allowedVariables),
        isBlank
      )
    },

    normalizeResponse(response) {
      if(response.errors) {
        throw new DS.AdapterError(response.errors)
      } else {
        return this.get('store').serializerFor('application').normalize(response.data)
      }
    }
  }
})
<|endoftext|>


<commit_before>var childProcess = require("child_process")
var path = require("path")

var env = process.env
env.NODE_ENV = "test"

var options={
  env:env,
  stdio:"inherit"
}

var command = path.join(".","node_modules",".bin","mocha")

try {
  childProcess.execSync(command,options)
}catch(ex){}
<commit_msg>- Use the spawn method in the script so that it will still work on version of node older than 0.12.<commit_after>var childProcess = require("child_process")
var path = require("path")

var env = process.env
env.NODE_ENV = "test"

var options = {
	env:   env,
	stdio: "inherit",
}

var command = path.join(".", "node_modules", ".bin", "mocha")
if (process.platform == "win32") command += ".cmd"
try {
	childProcess.spawn(command, options)
} catch (ex) {}
<|endoftext|>


<commit_before>define([
  'summernote/base/core/agent',
  'summernote/base/core/dom',
  'summernote/base/core/func',
  'summernote/base/core/list',
  'summernote/base/core/range'
], function (agent, dom, func, list, range) {
  var AirPopover = function (context) {
    var self = this;

    var $document = $(document);
    var $editable = context.layoutInfo.editable;
    var editable = $editable[0];

    var options = context.options;

    var innerMouseUp;

    this.events = {
      'summernote.keyup summernote.mouseup summernote.scroll': function () {
        innerMouseUp = true;
        self.update();
        self.setLastRange();
      },
      'summernote.change summernote.dialog.shown': function () {
        self.update();
        self.setLastRange();
      },
      'summernote.focusout': function (we, e) {
        // [workaround] Firefox doesn't support relatedTarget on focusout
        //  - Ignore hide action on focus out in FF.
        if (agent.isFF) {
          return;
        }

        if (!e.relatedTarget) {
          self.hide();
        }
      }
    };

    $editable.on('mousedown', function () {
      $document.on('mouseup', function () {
        if (!innerMouseUp) {
          self.update();
        }

        innerMouseUp = false;
        $document.off('mouseup');
      });
    });

    this.shouldInitialize = function () {
      return options.airMode &&
        options.popover &&
        options.popover.air &&
        typeof options.popover.air.hide === 'function' &&
        typeof options.popover.air.update === 'function';
    };

    this.initialize = function () {
      this.fontInstalledMap = {};
    };

    this.destroy = function () {
      delete this.fontInstalledMap;
    };

    this.isFontInstalled = function (name) {
      if (!self.fontInstalledMap.hasOwnProperty(name)) {
        self.fontInstalledMap[name] = agent.isFontInstalled(name) ||
          list.contains(options.fontNamesIgnoreCheck, name);
      }

      return self.fontInstalledMap[name];
    };

    this.getAvailablesFont = function () {
      return options.fontNames.filter(self.isFontInstalled);
    };

    this.setLastRange = function () {
      var currentRange = range.createFromSelection();
      if (currentRange && self.isAncestor(currentRange.sc, editable)) {
        self.lastRange = currentRange ? currentRange : self.lastRange;
      }
      return self.lastRange;
    };

    this.getLastRange = function () {
      return self.lastRange;
    };

    this.insertNode = function (node, rng) {
      if (!$editable.is(':focus')) {
        $editable.focus();
      }
      rng = rng || self.lastRange || range.create(editable);
      rng = rng.deleteContents();
      var info = splitPoint(rng.getStartPoint());

      if (info.rightNode && info.rightNode.parentNode) {
        info.rightNode.parentNode.insertBefore(node, info.rightNode);
      } else {
        if (!info.container || !self.isAncestor(info.container, editable)) {
          editable.appendChild(node);
        } else {
          info.container.appendChild(node);
        }
      }

      self.lastRange = range.createFromNodeAfter(node);
      self.lastRange.select();
    };

    this.moveCursorToEnd = function () {
      if (editable.lastChild || editable.lastElementChild) {
        range.createFromNodeAfter(editable.lastChild || editable.lastElementChild).select();
      }
    };

    this.pasteHTML = function (markup, rng) {
      if (!$editable.is(':focus')) {
        $editable.focus();
      }
      rng = rng || self.lastRange || range.create(editable);
      rng = rng.deleteContents();
      var info = splitPoint(rng.getStartPoint());

      var contentsContainer = $('

').html(markup)[0];
      if (contentsContainer && contentsContainer.childNodes) {
        var childNodes = list.from(contentsContainer.childNodes);

        var contents = childNodes.map(function (childNode) {
          if (info.rightNode && info.rightNode.parentNode) {
            info.rightNode.parentNode.insertBefore(childNode, info.rightNode);
          } else {
            if (!info.container || !self.isAncestor(info.container, editable)) {
              editable.appendChild(childNode);
            } else {
              info.container.appendChild(childNode);
            }
          }
          return childNode;
        });

        self.lastRange = range.createFromNodeAfter(list.last(contents));
        self.lastRange.select();
      }
    };

    this.update = function (force) {
      var styleInfo = context.invoke('editor.currentStyle');
      if (styleInfo.range && (!styleInfo.range.isCollapsed() || force)) {
        var rect = list.last(styleInfo.range.getClientRects());
        var bnd;
        if (rect) {
          bnd = func.rect2bnd(rect);
          options.popover.air.update(styleInfo, bnd);
        } else if (force) {
          options.popover.air.update(styleInfo, null);
        }
      } else {
        this.hide();
      }
    };

    this.hide = function () {
      options.popover.air.hide();
    };

    this.isAncestor = function (node, parentNode) {
      while (node) {
        if (node === parentNode) { return true; }

        node = node.parentNode;
      }
      return null;
    };

    function splitPoint(point) {
      if (dom.isEdgePoint(point) && dom.isRightEdgePoint(point)) {
        if (dom.isText(point.node)) {
          return {
            rightNode: point.node.nextSibling,
            container: point.node.parentNode
          };
        }

        return {
          container: point.node
        };
      }

      // split #text
      if (dom.isText(point.node)) {
        return {
          rightNode: point.node.splitText(point.offset),
          container: point.node.parentNode
        };
      } else {
        if (point.offset < point.node.childNodes.length) {
          return {
            rightNode: point.node.childNodes[point.offset],
            container: point.node
          };
        }
        return {
          container: point.node
        };
      }
    }
  };

  return AirPopover;
});
<commit_msg>fix(airPopover): Fix lastRange<commit_after>define([
  'summernote/base/core/agent',
  'summernote/base/core/dom',
  'summernote/base/core/func',
  'summernote/base/core/list',
  'summernote/base/core/range'
], function (agent, dom, func, list, range) {
  var AirPopover = function (context) {
    var self = this;

    var $document = $(document);
    var $editable = context.layoutInfo.editable;
    var editable = $editable[0];

    var options = context.options;

    var innerMouseUp;

    this.events = {
      'summernote.keyup summernote.mouseup summernote.scroll': function () {
        innerMouseUp = true;
        self.update();
        self.setLastRange();
      },
      'summernote.change summernote.dialog.shown': function () {
        self.update();
        self.setLastRange();
      },
      'summernote.focusout': function (we, e) {
        // [workaround] Firefox doesn't support relatedTarget on focusout
        //  - Ignore hide action on focus out in FF.
        if (agent.isFF) {
          return;
        }

        if (!e.relatedTarget) {
          self.hide();
        }
      }
    };

    $editable.on('mousedown', function () {
      $document.on('mouseup', function () {
        if (!innerMouseUp) {
          self.update();
          self.setLastRange();
        }

        innerMouseUp = false;
        $document.off('mouseup');
      });
    });

    this.shouldInitialize = function () {
      return options.airMode &&
        options.popover &&
        options.popover.air &&
        typeof options.popover.air.hide === 'function' &&
        typeof options.popover.air.update === 'function';
    };

    this.initialize = function () {
      this.fontInstalledMap = {};
    };

    this.destroy = function () {
      delete this.fontInstalledMap;
    };

    this.isFontInstalled = function (name) {
      if (!self.fontInstalledMap.hasOwnProperty(name)) {
        self.fontInstalledMap[name] = agent.isFontInstalled(name) ||
          list.contains(options.fontNamesIgnoreCheck, name);
      }

      return self.fontInstalledMap[name];
    };

    this.getAvailablesFont = function () {
      return options.fontNames.filter(self.isFontInstalled);
    };

    this.setLastRange = function () {
      var currentRange = range.createFromSelection();
      if (currentRange && (self.isAncestor(currentRange.sc, editable) || currentRange.sc === editable)) {
        self.lastRange = currentRange ? currentRange : self.lastRange;
      }
      return self.lastRange;
    };

    this.getLastRange = function () {
      return self.lastRange;
    };

    this.insertNode = function (node, rng) {
      if (!$editable.is(':focus')) {
        $editable.focus();
      }
      rng = rng || self.lastRange || range.create(editable);
      rng = rng.deleteContents();
      var info = splitPoint(rng.getStartPoint());

      if (info.rightNode && info.rightNode.parentNode) {
        info.rightNode.parentNode.insertBefore(node, info.rightNode);
      } else {
        if (!info.container || !self.isAncestor(info.container, editable)) {
          editable.appendChild(node);
        } else {
          info.container.appendChild(node);
        }
      }

      self.lastRange = range.createFromNodeAfter(node);
      self.lastRange.select();
    };

    this.moveCursorToEnd = function () {
      if (editable.lastChild || editable.lastElementChild) {
        range.createFromNodeAfter(editable.lastChild || editable.lastElementChild).select();
      }
    };

    this.pasteHTML = function (markup, rng) {
      if (!$editable.is(':focus')) {
        $editable.focus();
      }
      rng = rng || self.lastRange || range.create(editable);
      rng = rng.deleteContents();
      var info = splitPoint(rng.getStartPoint());

      var contentsContainer = $('

').html(markup)[0];
      if (contentsContainer && contentsContainer.childNodes) {
        var childNodes = list.from(contentsContainer.childNodes);

        var contents = childNodes.map(function (childNode) {
          if (info.rightNode && info.rightNode.parentNode) {
            info.rightNode.parentNode.insertBefore(childNode, info.rightNode);
          } else {
            if (!info.container || !self.isAncestor(info.container, editable)) {
              editable.appendChild(childNode);
            } else {
              info.container.appendChild(childNode);
            }
          }
          return childNode;
        });

        self.lastRange = range.createFromNodeAfter(list.last(contents));
        self.lastRange.select();
      }
    };

    this.update = function (force) {
      var styleInfo = context.invoke('editor.currentStyle');
      if (styleInfo.range && (!styleInfo.range.isCollapsed() || force)) {
        var rect = list.last(styleInfo.range.getClientRects());
        var bnd;
        if (rect) {
          bnd = func.rect2bnd(rect);
          options.popover.air.update(styleInfo, bnd);
        } else if (force) {
          options.popover.air.update(styleInfo, null);
        }
      } else {
        this.hide();
      }
    };

    this.hide = function () {
      options.popover.air.hide();
    };

    this.isAncestor = function (node, parentNode) {
      while (node) {
        if (node === parentNode) { return true; }

        node = node.parentNode;
      }
      return null;
    };

    function splitPoint(point) {
      if (dom.isEdgePoint(point) && dom.isRightEdgePoint(point)) {
        if (dom.isText(point.node)) {
          return {
            rightNode: point.node.nextSibling,
            container: point.node.parentNode
          };
        }

        return {
          container: point.node
        };
      }

      // split #text
      if (dom.isText(point.node)) {
        return {
          rightNode: point.node.splitText(point.offset),
          container: point.node.parentNode
        };
      } else {
        if (point.offset < point.node.childNodes.length) {
          return {
            rightNode: point.node.childNodes[point.offset],
            container: point.node
          };
        }
        return {
          container: point.node
        };
      }
    }
  };

  return AirPopover;
});
<|endoftext|>


<commit_before>var CloudCmd, Util, DOM, CloudFunc, ace, DiffProto, diff_match_patch, Zip;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.Edit = EditProto;

    function EditProto() {
        var Name        = 'Edit',
            Loading     = false,
            DIR         = CloudCmd.LIBDIRCLIENT + 'edit/',
            LIBDIR      = CloudCmd.LIBDIR,
            Info        = DOM.CurrentInfo,
            Value,
            Edit        = this,
            Diff,
            Emmet,
            Ace,
            Session,
            Modelist,
            Msg,
            Events      = DOM.Events,
            Dialog      = DOM.Dialog,
            Images      = DOM.Images,
            Element, JSHintConfig, EditConfig;

       function init() {
            Loading   = true;
            Util.loadOnLoad([
                CloudCmd.View,
                load,
                Edit.show
            ]);
        }

        this.show                       = function(value) {
            var mode, htmlMode, jsMode, isHTML, isJS, modesByName,
                isStr       = Util.isString(value),
                name        = Info.name,
                isDir       = Info.isDir,
                focus       = function() {
                    Ace.focus();
                    Ace.clearSelection();
                    Ace.moveCursorTo(0, 0);
                };

            if (!Loading) {
                Images.showLoad();

                if (!Element) {
                    Element         = DOM.anyload({
                        name        : 'div',
                        style   :
                            'width      : 100%;'    +
                            'height     : 100%;'    +
                            'font       : 16px "Droid Sans Mono";' +
                            'position   : absolute;',
                        not_append : true
                    });

                  initAce();

                  Events.add({
                      drop      : onDrop,
                      dragover  : function(event) {
                          event.preventDefault();
                      }
                  }, Element);
                }

                modesByName = Modelist.modesByName;

                if (isDir)
                    mode    = modesByName.json.mode;
                else
                    mode    = Modelist.getModeForPath(name).mode;

                htmlMode    = modesByName.html.mode;
                jsMode      = modesByName.javascript.mode;

                isHTML      = mode === htmlMode;
                isJS        = mode === jsMode;

                Session.setMode(mode);
                setUseOfWorker(mode);

                setEmmet(isHTML);

                Util.ifExec(isStr, function() {
                    var UndoManager = ace.require('ace/undomanager').UndoManager;

                    Ace.setValue(Value);
                    CloudCmd.View.show(Element, {
                        beforeClose: isChanged,
                        afterShow: focus
                    });

                    Session.setUndoManager(new UndoManager());
                }, function(callback) {
                    Info.getData(function(data) {
                        Value = data;

                        if (isJS && Session.getUseWorker())
                            setJsHintConfig();

                        callback();
                    });
                });
            }
        };

        this.hide                       =  function() {
            CloudCmd.View.hide();
        };

        this.goToLine                   = function() {
            var msg     = 'Enter line number:',
                cursor  = Ace.selection.getCursor(),
                number  = cursor.row + 1,
                line    = Dialog.prompt(msg, number);

            number      = line - 0;

            if (number)
                Ace.gotoLine(number);
        };

        function isChanged() {
            var is,
                value   = Ace.getValue(),
                isEqual = value === Value,
                msg     = 'Do you want to save changes to ' + name + '?';

            if (!isEqual) {
                is = Dialog.confirm(msg);

                if (is)
                    save();
            }
        }

        function setEmmet(isHTML) {
            getEditConfig(function(config) {
                var extensions  = config.extensions,
                    isEmmet     = extensions.emmet;

                if (isEmmet)
                    Util.ifExec(Emmet, function() {
                            if (Emmet)
                                Ace.setOption('enableEmmet', isHTML);
                        }, function(callback) {
                            var url;

                            if (!isHTML)
                                Util.exec(callback);
                            else {
                                url = CloudFunc.getJoinURL([
                                    DIR + 'emmet.js',
                                    DIR + 'ext-emmet.js'
                                ]);

                                DOM.jsload(url, function() {
                                    Emmet = ace.require('ace/ext/emmet');
                                    Emmet.setCore(window.emmet);
                                    Util.exec(callback);
                                });
                            }
                        });
                });
        }

        function setUseOfWorker(mode) {
            var isMatch,
                isStr   = Util.isString(mode),
                regStr  = 'coffee|css|html|javascript|json|lua|php|xquery',
                regExp  = new RegExp(regStr);

            if (isStr)
                isMatch = mode.match(regExp);

            Session.setUseWorker(isMatch);
        }

        function initAce() {
            Ace     = ace.edit(Element);
            Session = Ace.getSession();

            Ace.commands.addCommand({
                name    : 'hide',
                bindKey : { win: 'Esc',  mac: 'Esc' },
                exec    : function () {
                    Edit.hide();
                }
            });

            Ace.commands.addCommand({
                name    : 'goToLine',
                bindKey : { win: 'Ctrl-G',  mac: 'Command-G' },
                exec    : function () {
                    Edit.goToLine();
                }
            });

            Ace.commands.addCommand({
                name    : 'save',
                bindKey : { win: 'Ctrl-S',  mac: 'Command-S' },
                exec    : save
            });

            Ace.commands.addCommand({
                name    : 'saveMC',
                bindKey : { win: 'F2',  mac: 'F2' },
                exec    : save
            });

            ace.require('ace/ext/language_tools');
            Modelist = ace.require('ace/ext/modelist');

            getEditConfig(function(config) {
                var options      = config.options;

                Ace.setOptions(options);
            });
        }

        function save () {
            var path    = Info.path,
                value   = Ace.getValue();

            CloudCmd.getConfig(function(config) {
                var isDiff      = config.diff,
                    isZip       = config.zip;

                Util.ifExec(!isDiff, function(patch) {
                    var query           = '',
                        MAX_SIZE        = CloudFunc.MAX_FILE_SIZE,
                        patchLength     = patch.length,
                        length          = Value.length,
                        isLessMaxLength = length < MAX_SIZE,
                        isLessLength    = isLessMaxLength && patchLength < length,
                        isStr           = Util.isString(patch);

                    Value               = value;

                    if (isStr && patch && isLessLength)
                        query           = '?patch';
                    else
                        patch           = false;

                    Util.ifExec(!isZip || query, function(equal, data) {
                        var result  = data || patch || Value,
                            url     = path + query;

                        DOM.RESTful.write(url, result , onSave);
                    }, function(func) {
                        zip(value, function(error, data) {
                            if (error)
                                Util.log(error);

                            query = '?unzip';
                            func(null, data);
                        });
                    });

                }, Util.bind(doDiff, path));
            });
        }

        function doDiff(path, callback) {
            var value = Ace.getValue();

            diff(value, function(patch) {
                var isAllowed = DOM.Storage.isAllowed();

                Util.ifExec(!isAllowed, callback, function(func) {
                        DOM.checkStorageHash(path, function(error, equal) {
                            if (!equal)
                                patch = '';

                            func(patch);
                        });
                });
            });
        }

        function diff(newValue, callback) {
            var libs            = [
                    LIBDIR + 'diff/diff-match-patch.js',
                    LIBDIR + 'diff.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.jsload(url, function() {
                var patch,
                    isAllowed   = DOM.Storage.isAllowed();

                if (!Diff)
                    Diff        = new DiffProto(diff_match_patch);

                Util.ifExec(!isAllowed, function() {
                    patch       = Diff.createPatch(Value, newValue);
                    Util.exec(callback, patch);
                }, function(func) {
                    var path = Info.path;

                    DOM.getDataFromStorage(path, function(data) {
                        if (data)
                            Value   = data;

                        func();
                    });
                });
            });
        }

        function zip(value, callback) {
            var dir             = CloudCmd.LIBDIRCLIENT,
                libs            = [
                    dir + 'zip/dist/pako.js',
                    dir + 'zip.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.jsload(url, function() {
                Zip.pack(value, callback);
            });
        }

        function setJsHintConfig(callback) {
            var JSHINT_PATH = '/.jshintrc',
                func        = function() {
                    var worker  = Session.$worker;

                    if (worker)
                        worker.send('changeOptions', [JSHintConfig]);

                    Util.exec(callback);
                };

            Util.ifExec(JSHintConfig, func, function() {
                DOM.ajax({
                    url     :  JSHINT_PATH,
                    success : function(data) {
                        JSHintConfig = Util.parseJSON(data);
                        func();
                    }
                });
            });
        }

        function getEditConfig(callback) {
            var CONFIG_PATH = '/json/edit.json',
                func        = Util.retExec(callback);

            Util.ifExec(EditConfig, function() {
                func(EditConfig);
            }, function() {
                DOM.ajax({
                    url     : CONFIG_PATH,
                    success : function(data) {
                        EditConfig = data;
                        func(EditConfig);
                    }
                });
            });
        }

        function load(callback) {
            var files  = [
                    DIR + 'theme-tomorrow_night_blue.js',
                    DIR + 'ext-language_tools.js',
                    DIR + 'ext-searchbox.js',
                    DIR + 'ext-modelist.js'
                ],

                ace     = DIR + 'ace.js',
                url     = CloudFunc.getJoinURL(files);

            Util.time(Name + ' load');

            DOM.anyLoadOnLoad([ace, url], function() {
                Util.timeEnd(Name + ' load');
                Loading = false;
                Util.exec(callback);
            });
        }

        function onSave(text) {
            var ret,
                isError = Util.isContainStrAtBegin(text, 'error'),
                path    = Info.path,
                msg     = '\nShould I save file anyway?';

            if (!isError) {
                Edit.showMessage(text);
                DOM.saveDataToStorage(path, Value);
                DOM.setCurrentSize(Value.length);
            } else {
                ret     = Dialog.confirm(text + msg);

                if (ret)
                    DOM.RESTful.write(path, Value, onSave);
            }
        }

         function onDrop(event) {
            var reader, i, n, file, files,
                onLoad   =  function(event) {
                    var data    = event.target.result;

                    Ace.setValue(data);
                };

            event.preventDefault();

            files               = event.dataTransfer.files;

            if (files.length) {
                n               = files.length;

                for (i = 0; i < n; i++) {
                    reader          = new FileReader();
                    file            = files[i];

                    DOM.Events.add('load', onLoad, reader);
                    reader.readAsBinaryString(file);
                }
            }
        }

        this.showMessage    = function(text) {
            var parent,
                HIDE_TIME = 2000;

            if (!Msg) {
                DOM.cssSet({
                    id      : 'msg-css',
                    inner   : '#js-view .msg {'     +
                                'z-index'           + ': 1;'                    +
                                'background-color'  + ': #7285B7;'              +
                                'color'             + ': #D1F1A9;'              +
                                'position'          + ': fixed;'                +
                                'left'              + ': 40%;'                  +
                                'top'               + ': 25px;'                 +
                                'padding'           + ': 5px;'                  +
                                'opacity'           + ': 0.9;'                  +
                                'transition'        + ': ease 0.5s;'            +
                            '}'
                });
                parent  = Element;

                Msg     = DOM.anyload({
                    name        : 'div',
                    className   : 'msg',
                    parent      : parent
                });
            }

            Msg.innerHTML = text;
            DOM.show(Msg);
            setTimeout(Util.retExec(DOM.hide, Msg), HIDE_TIME);
        };

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<commit_msg>refactor(edit) onDrop: for -> forEach<commit_after>var CloudCmd, Util, DOM, CloudFunc, ace, DiffProto, diff_match_patch, Zip;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.Edit = EditProto;

    function EditProto() {
        var Name        = 'Edit',
            Loading     = false,
            DIR         = CloudCmd.LIBDIRCLIENT + 'edit/',
            LIBDIR      = CloudCmd.LIBDIR,
            Info        = DOM.CurrentInfo,
            Value,
            Edit        = this,
            Diff,
            Emmet,
            Ace,
            Session,
            Modelist,
            Msg,
            Events      = DOM.Events,
            Dialog      = DOM.Dialog,
            Images      = DOM.Images,
            Element, JSHintConfig, EditConfig;

       function init() {
            Loading   = true;
            Util.loadOnLoad([
                CloudCmd.View,
                load,
                Edit.show
            ]);
        }

        this.show                       = function(value) {
            var mode, htmlMode, jsMode, isHTML, isJS, modesByName,
                isStr       = Util.isString(value),
                name        = Info.name,
                isDir       = Info.isDir,
                focus       = function() {
                    Ace.focus();
                    Ace.clearSelection();
                    Ace.moveCursorTo(0, 0);
                };

            if (!Loading) {
                Images.showLoad();

                if (!Element) {
                    Element         = DOM.anyload({
                        name        : 'div',
                        style   :
                            'width      : 100%;'    +
                            'height     : 100%;'    +
                            'font       : 16px "Droid Sans Mono";' +
                            'position   : absolute;',
                        not_append : true
                    });

                  initAce();

                  Events.add({
                      drop      : onDrop,
                      dragover  : function(event) {
                          event.preventDefault();
                      }
                  }, Element);
                }

                modesByName = Modelist.modesByName;

                if (isDir)
                    mode    = modesByName.json.mode;
                else
                    mode    = Modelist.getModeForPath(name).mode;

                htmlMode    = modesByName.html.mode;
                jsMode      = modesByName.javascript.mode;

                isHTML      = mode === htmlMode;
                isJS        = mode === jsMode;

                Session.setMode(mode);
                setUseOfWorker(mode);

                setEmmet(isHTML);

                Util.ifExec(isStr, function() {
                    var UndoManager = ace.require('ace/undomanager').UndoManager;

                    Ace.setValue(Value);
                    CloudCmd.View.show(Element, {
                        beforeClose: isChanged,
                        afterShow: focus
                    });

                    Session.setUndoManager(new UndoManager());
                }, function(callback) {
                    Info.getData(function(data) {
                        Value = data;

                        if (isJS && Session.getUseWorker())
                            setJsHintConfig();

                        callback();
                    });
                });
            }
        };

        this.hide                       =  function() {
            CloudCmd.View.hide();
        };

        this.goToLine                   = function() {
            var msg     = 'Enter line number:',
                cursor  = Ace.selection.getCursor(),
                number  = cursor.row + 1,
                line    = Dialog.prompt(msg, number);

            number      = line - 0;

            if (number)
                Ace.gotoLine(number);
        };

        function isChanged() {
            var is,
                value   = Ace.getValue(),
                isEqual = value === Value,
                msg     = 'Do you want to save changes to ' + name + '?';

            if (!isEqual) {
                is = Dialog.confirm(msg);

                if (is)
                    save();
            }
        }

        function setEmmet(isHTML) {
            getEditConfig(function(config) {
                var extensions  = config.extensions,
                    isEmmet     = extensions.emmet;

                if (isEmmet)
                    Util.ifExec(Emmet, function() {
                            if (Emmet)
                                Ace.setOption('enableEmmet', isHTML);
                        }, function(callback) {
                            var url;

                            if (!isHTML)
                                Util.exec(callback);
                            else {
                                url = CloudFunc.getJoinURL([
                                    DIR + 'emmet.js',
                                    DIR + 'ext-emmet.js'
                                ]);

                                DOM.jsload(url, function() {
                                    Emmet = ace.require('ace/ext/emmet');
                                    Emmet.setCore(window.emmet);
                                    Util.exec(callback);
                                });
                            }
                        });
                });
        }

        function setUseOfWorker(mode) {
            var isMatch,
                isStr   = Util.isString(mode),
                regStr  = 'coffee|css|html|javascript|json|lua|php|xquery',
                regExp  = new RegExp(regStr);

            if (isStr)
                isMatch = mode.match(regExp);

            Session.setUseWorker(isMatch);
        }

        function initAce() {
            Ace     = ace.edit(Element);
            Session = Ace.getSession();

            Ace.commands.addCommand({
                name    : 'hide',
                bindKey : { win: 'Esc',  mac: 'Esc' },
                exec    : function () {
                    Edit.hide();
                }
            });

            Ace.commands.addCommand({
                name    : 'goToLine',
                bindKey : { win: 'Ctrl-G',  mac: 'Command-G' },
                exec    : function () {
                    Edit.goToLine();
                }
            });

            Ace.commands.addCommand({
                name    : 'save',
                bindKey : { win: 'Ctrl-S',  mac: 'Command-S' },
                exec    : save
            });

            Ace.commands.addCommand({
                name    : 'saveMC',
                bindKey : { win: 'F2',  mac: 'F2' },
                exec    : save
            });

            ace.require('ace/ext/language_tools');
            Modelist = ace.require('ace/ext/modelist');

            getEditConfig(function(config) {
                var options      = config.options;

                Ace.setOptions(options);
            });
        }

        function save () {
            var path    = Info.path,
                value   = Ace.getValue();

            CloudCmd.getConfig(function(config) {
                var isDiff      = config.diff,
                    isZip       = config.zip;

                Util.ifExec(!isDiff, function(patch) {
                    var query           = '',
                        MAX_SIZE        = CloudFunc.MAX_FILE_SIZE,
                        patchLength     = patch.length,
                        length          = Value.length,
                        isLessMaxLength = length < MAX_SIZE,
                        isLessLength    = isLessMaxLength && patchLength < length,
                        isStr           = Util.isString(patch);

                    Value               = value;

                    if (isStr && patch && isLessLength)
                        query           = '?patch';
                    else
                        patch           = false;

                    Util.ifExec(!isZip || query, function(equal, data) {
                        var result  = data || patch || Value,
                            url     = path + query;

                        DOM.RESTful.write(url, result , onSave);
                    }, function(func) {
                        zip(value, function(error, data) {
                            if (error)
                                Util.log(error);

                            query = '?unzip';
                            func(null, data);
                        });
                    });

                }, Util.bind(doDiff, path));
            });
        }

        function doDiff(path, callback) {
            var value = Ace.getValue();

            diff(value, function(patch) {
                var isAllowed = DOM.Storage.isAllowed();

                Util.ifExec(!isAllowed, callback, function(func) {
                        DOM.checkStorageHash(path, function(error, equal) {
                            if (!equal)
                                patch = '';

                            func(patch);
                        });
                });
            });
        }

        function diff(newValue, callback) {
            var libs            = [
                    LIBDIR + 'diff/diff-match-patch.js',
                    LIBDIR + 'diff.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.jsload(url, function() {
                var patch,
                    isAllowed   = DOM.Storage.isAllowed();

                if (!Diff)
                    Diff        = new DiffProto(diff_match_patch);

                Util.ifExec(!isAllowed, function() {
                    patch       = Diff.createPatch(Value, newValue);
                    Util.exec(callback, patch);
                }, function(func) {
                    var path = Info.path;

                    DOM.getDataFromStorage(path, function(data) {
                        if (data)
                            Value   = data;

                        func();
                    });
                });
            });
        }

        function zip(value, callback) {
            var dir             = CloudCmd.LIBDIRCLIENT,
                libs            = [
                    dir + 'zip/dist/pako.js',
                    dir + 'zip.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.jsload(url, function() {
                Zip.pack(value, callback);
            });
        }

        function setJsHintConfig(callback) {
            var JSHINT_PATH = '/.jshintrc',
                func        = function() {
                    var worker  = Session.$worker;

                    if (worker)
                        worker.send('changeOptions', [JSHintConfig]);

                    Util.exec(callback);
                };

            Util.ifExec(JSHintConfig, func, function() {
                DOM.ajax({
                    url     :  JSHINT_PATH,
                    success : function(data) {
                        JSHintConfig = Util.parseJSON(data);
                        func();
                    }
                });
            });
        }

        function getEditConfig(callback) {
            var CONFIG_PATH = '/json/edit.json',
                func        = Util.retExec(callback);

            Util.ifExec(EditConfig, function() {
                func(EditConfig);
            }, function() {
                DOM.ajax({
                    url     : CONFIG_PATH,
                    success : function(data) {
                        EditConfig = data;
                        func(EditConfig);
                    }
                });
            });
        }

        function load(callback) {
            var files  = [
                    DIR + 'theme-tomorrow_night_blue.js',
                    DIR + 'ext-language_tools.js',
                    DIR + 'ext-searchbox.js',
                    DIR + 'ext-modelist.js'
                ],

                ace     = DIR + 'ace.js',
                url     = CloudFunc.getJoinURL(files);

            Util.time(Name + ' load');

            DOM.anyLoadOnLoad([ace, url], function() {
                Util.timeEnd(Name + ' load');
                Loading = false;
                Util.exec(callback);
            });
        }

        function onSave(text) {
            var ret,
                isError = Util.isContainStrAtBegin(text, 'error'),
                path    = Info.path,
                msg     = '\nShould I save file anyway?';

            if (!isError) {
                Edit.showMessage(text);
                DOM.saveDataToStorage(path, Value);
                DOM.setCurrentSize(Value.length);
            } else {
                ret     = Dialog.confirm(text + msg);

                if (ret)
                    DOM.RESTful.write(path, Value, onSave);
            }
        }

         function onDrop(event) {
            var reader, i, n, file, files,
                onLoad   =  function(event) {
                    var data    = event.target.result;

                    Ace.setValue(data);
                };

            event.preventDefault();

            files   = event.dataTransfer.files;

            if (files)
                files.forEach(function(file) {
                    reader  = new FileReader();
                    DOM.Events.add('load', onLoad, reader);
                    reader.readAsBinaryString(file);
                });
        }

        this.showMessage    = function(text) {
            var parent,
                HIDE_TIME = 2000;

            if (!Msg) {
                DOM.cssSet({
                    id      : 'msg-css',
                    inner   : '#js-view .msg {'     +
                                'z-index'           + ': 1;'                    +
                                'background-color'  + ': #7285B7;'              +
                                'color'             + ': #D1F1A9;'              +
                                'position'          + ': fixed;'                +
                                'left'              + ': 40%;'                  +
                                'top'               + ': 25px;'                 +
                                'padding'           + ': 5px;'                  +
                                'opacity'           + ': 0.9;'                  +
                                'transition'        + ': ease 0.5s;'            +
                            '}'
                });
                parent  = Element;

                Msg     = DOM.anyload({
                    name        : 'div',
                    className   : 'msg',
                    parent      : parent
                });
            }

            Msg.innerHTML = text;
            DOM.show(Msg);
            setTimeout(Util.retExec(DOM.hide, Msg), HIDE_TIME);
        };

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<|endoftext|>